home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Technical Documentation / C.S.M.P. Digests / csmp-digest-v3-036 / doubleCR.1 < prev   
Encoding:
Text File  |  1994-07-07  |  142.3 KB  |  3,568 lines

  1. C.S.M.P. Digest             Thu, 16 Jun 94       Volume 3 : Issue 36
  2.  
  3. Today's Topics:
  4.  
  5.         Apple Event example
  6.         Faster Square Root Algorithm
  7.         How to save alpha in PICT files?
  8.         Open Transport & ASLM
  9.         Sending the Mac Screen Image
  10.         What are Universal Headers?
  11.  
  12.  
  13.  
  14. The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
  15. (pottier@clipper.ens.fr).
  16.  
  17. The digest is a collection of article threads from the internet newsgroup
  18. comp.sys.mac.programmer.  It is designed for people who read c.s.m.p. semi-
  19. regularly and want an archive of the discussions.  If you don't know what a
  20. newsgroup is, you probably don't have access to it.  Ask your systems
  21. administrator(s) for details.  If you don't have access to news, you may
  22. still be able to post messages to the group by using a mail server like
  23. anon.penet.fi (mail help@anon.penet.fi for more information).
  24.  
  25. Each issue of the digest contains one or more sets of articles (called
  26. threads), with each set corresponding to a 'discussion' of a particular
  27. subject.  The articles are not edited; all articles included in this digest
  28. are in their original posted form (as received by our news server at
  29. nef.ens.fr).  Article threads are not added to the digest until the last
  30. article added to the thread is at least two weeks old (this is to ensure that
  31. the thread is dead before adding it to the digest).  Article threads that
  32. consist of only one message are generally not included in the digest.
  33.  
  34. The digest is officially distributed by two means, by email and ftp.
  35.  
  36. If you want to receive the digest by mail, send email to listserv@ens.fr
  37. with no subject and one of the following commands as body:
  38.     help                        Sends you a summary of commands
  39.     subscribe csmp-digest Your Name    Adds you to the mailing list
  40.     signoff csmp-digest            Removes you from the list
  41. Once you have subscribed, you will automatically receive each new
  42. issue as it is created.
  43.  
  44. The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
  45. Questions related to the ftp site should be directed to
  46. scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
  47. digest are available there.
  48.  
  49. Also, the digests are available to WAIS users.  To search back issues
  50. with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use
  51. http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html.
  52.  
  53.  
  54. -------------------------------------------------------
  55.  
  56. >From farago@onyx.ill.fr (Bela Farago)
  57. Subject: Apple Event example
  58. Date: Thu, 2 Jun 94 13:06:18 GMT
  59. Organization: ILL - Grenoble FRANCE
  60.  
  61. Hi,
  62.  
  63. please forgive me if it is trivial but I am programming just by hobby (well
  64. not really but this is not my main job)
  65. I need to write a rather trivial code resource which sends the equivalent of
  66. the following AppleScript
  67.  
  68. tell application anApplication
  69.     save document 1
  70. end tell
  71.  
  72. An Application is an application :)
  73.  
  74. It is hard to digest the volume VI of IM. and I could not find simple
  75. example on ftp.apple.com. (I did find some but were not very clear to me) I
  76. am bit lost in descriptors and direct objects etc. Could anybody give me
  77. pointers to simple examples?
  78.                                     Bela Farago (farago@ill.fr)
  79.  
  80. ps: No flames please, you can always just ignore this message.
  81.  
  82. +++++++++++++++++++++++++++
  83.  
  84. >From greer@utdallas.edu (Dale M. Greer)
  85. Date: 2 Jun 1994 16:54:39 GMT
  86. Organization: The University of Texas at Dallas
  87.  
  88. Bela Farago (farago@onyx.ill.fr) wrote:
  89. > Hi,
  90.  
  91. > please forgive me if it is trivial but I am programming just by hobby (well
  92. > not really but this is not my main job)
  93. > I need to write a rather trivial code resource which sends the equivalent of
  94. > the following AppleScript
  95.  
  96. > tell application anApplication
  97. >     save document 1
  98. > end tell
  99.  
  100. > An Application is an application :)
  101.  
  102. > It is hard to digest the volume VI of IM. and I could not find simple
  103. > example on ftp.apple.com. (I did find some but were not very clear to me) I
  104. > am bit lost in descriptors and direct objects etc. Could anybody give me
  105. > pointers to simple examples?
  106. >                                     Bela Farago (farago@ill.fr)
  107.  
  108. > ps: No flames please, you can always just ignore this message.
  109.  
  110.  
  111. Here's how I did it.
  112.  
  113. /**************************************************** MyCreateDocContainer */
  114. // 07-APR-94 : Dale M. Greer
  115.  
  116. #pragma segment AEvents
  117. void MyCreateDocContainer(AEDesc *myDocContainer, char *docName)
  118. {
  119.     AEDesc myDocDescRec, nullDescRec;
  120.     OSErr err;
  121.  
  122.     // Prepare to make something from nothing
  123.     err = AECreateDesc(typeNull, nil, 0, &nullDescRec);
  124.  
  125.     // This document container just contains the document name
  126.     err = AECreateDesc(typeChar, docName, strlen(docName), &myDocDescRec);
  127.  
  128.     // Encapsulate the object
  129.     err = CreateObjSpecifier((DescType)cDocument, &nullDescRec, 
  130.         (DescType)formName, &myDocDescRec, true, myDocContainer);
  131.  
  132.     AEDisposeDesc(&nullDescRec);
  133. }
  134.  
  135. /********************************************************** SaveDocumentAs */
  136. // 07-APR-94 : Dale M. Greer
  137.  
  138. #pragma segment AEvents
  139. void SaveDocumentAs(AEAddressDesc *theAddress, char *docName, char *saveName)
  140. {
  141.     OSErr err;
  142.     AppleEvent appleEvent, reply;
  143.     AEDesc myDocDescRec, theName;
  144.  
  145.     err = AECreateAppleEvent(kAECoreSuite, kAESave, theAddress,
  146.             kAutoGenerateReturnID, 1L, &appleEvent);
  147.  
  148.     // Make the doc container
  149.     MyCreateDocContainer(&myDocDescRec, docName);
  150.  
  151.     // Append it to the appleEvent
  152.     AEPutParamDesc(&appleEvent, keyDirectObject, &myDocDescRec);
  153.  
  154.     // Append the new filename descriptor to the appleEvent
  155.     AECreateDesc(typeChar, saveName, strlen(saveName), &theName);
  156.     AEPutParamDesc(&appleEvent, keyAEFile, &theName);
  157.  
  158.     // Send it to the Application
  159.     err = AESend(&appleEvent, &reply, kAEWaitReply + kAENeverInteract,
  160.             kAENormalPriority, kAEDefaultTimeout,
  161.             (IdleProcPtr) MyIdleFunction, nil);
  162.  
  163.     AEDisposeDesc(&myDocDescRec);
  164.     AEDisposeDesc(&appleEvent);
  165.     AEDisposeDesc(&reply);
  166. }
  167.  
  168.  
  169. You get the address of the target application when you launch it, or if it
  170. is already launched, use the following routine, where "creator" is the
  171. creator type of your application.  For example, this creator type is
  172. 'XCEL' for Excel, 'ttxt' for TeachText, etc.
  173.  
  174. // This function originated from James "im" Beninghaus of Apple DTS
  175. /*********************************************************** AppLaunched */
  176. // Find the process serial number of your application
  177.  
  178. #pragma segment Launch
  179. Boolean AppLaunched(AEAddressDesc *theAddress, OSType creator,
  180.                     ProcessSerialNumber *PSN)
  181. {
  182.     OSErr                osErr;
  183.     ProcessSerialNumber process;
  184.     ProcessInfoRec        procInfo;
  185.     Str255                procName;
  186.     FSSpec procSpec;
  187.     
  188.     osErr = noErr;
  189.     process.highLongOfPSN = 0;
  190.     process.lowLongOfPSN  = 0;
  191.     
  192.     procInfo.processInfoLength    = sizeof(procInfo);
  193.     procInfo.processName        = procName;
  194.     procInfo.processAppSpec        = &procSpec;
  195.  
  196.     while (procNotFound != (osErr = GetNextProcess(&process))) {
  197.         if (noErr == (osErr = GetProcessInformation(&process, &procInfo))) {
  198.             if (procInfo.processSignature == creator) {
  199.                 AECreateDesc(typeProcessSerialNumber, (Ptr)&process, 
  200.                     sizeof(ProcessSerialNumber), theAddress);
  201.                     *PSN = process;
  202.                 return(true);
  203.             }
  204.         }
  205.     }
  206.     return(false);
  207. }
  208.  
  209. In summary, the program snippet accomplishing what you desire would
  210. look like this.
  211.  
  212. if (AppLaunched(&theAddress, theCreator, &PSN) {
  213.     SaveDocumentAs(&theAddress, &docName, &saveName);
  214. }
  215.  
  216. If the application is not already launched, there are a number of ways
  217. to launch it, but I will leave that as an exercise for the reader, or
  218. for a later tutorial if you're still having problems.
  219.  
  220. --
  221.  
  222. Dale Greer, greer@utdallas.edu
  223. "They know that it is human nature to take up causes whereby a man may
  224.  oppress his neighbor, no matter how unjustly. ... Hence they have had
  225.  no trouble in finding men who would preach the damnability and heresy
  226.  of the new doctrine from the very pulpit..." - Galileo Galilei, 1615
  227.  
  228.  
  229. ---------------------------
  230.  
  231. >From busfield@hurricane.seas.ucla.edu (John D. Busfield)
  232. Subject: Faster Square Root Algorithm
  233. Date: Tue, 3 May 1994 17:23:52 GMT
  234. Organization: School of Engineering & Applied Science, UCLA.
  235.  
  236.     Does anyone have an algorithm or code for computing square roots.
  237. The emphasis is on speed rather than accuracy in that I only need the
  238. result rounded to the nearest integer (ie sqrt(1000) = 31 or 32).
  239. Thanks in advance.
  240.  
  241. John Busfield
  242. busfield@hurricane.seas.ucla.edu
  243.  
  244.  
  245. +++++++++++++++++++++++++++
  246.  
  247. >From rmah@panix.com (Robert S. Mah)
  248. Date: Tue, 03 May 1994 17:41:55 -0500
  249. Organization: One Step Beyond
  250.  
  251. busfield@hurricane.seas.ucla.edu (John D. Busfield) wrote:
  252.  
  253. >     Does anyone have an algorithm or code for computing square roots.
  254. > The emphasis is on speed rather than accuracy in that I only need the
  255. > result rounded to the nearest integer (ie sqrt(1000) = 31 or 32).
  256.  
  257. There is an article on generating very fast square root aproximations
  258. in the book "Graphics Gems", Ed. Glassner. 
  259.  
  260. It generates a lookup table which is indexed by munging the exponent
  261. of the argument and then uses the mantissa to do an (linear?) 
  262. aproximation to the final result.  It's fairly accurate to within a few
  263. decimal points.  I think the source code is also available somewhere 
  264. on the net, but I'm afraid I don't know where.
  265.  
  266. Another option, since you only want integer aproximations, is to create a 
  267. table of squares and do a binary search over it.  A 1000 element table 
  268. will give you a range of 1->1,000,000 with an average of log2(1000) = 10 
  269. lookups using a simple binary search.  A table with 32K or so elements will
  270.  
  271. have a range of 1->1,000,000,000 and will be searchable in log2(32K) = 30 
  272. lookups.  If you can spare a few dozen K, then this may be fast enough.
  273.  
  274. Cheers,
  275. Rob
  276. ___________________________________________________________________________
  277. Robert S. Mah  -=-  One Step Beyond  -=-  212-947-6507  -=-  rmah@panix.com
  278.  
  279. +++++++++++++++++++++++++++
  280.  
  281. >From gewekean@studentg.msu.edu (Andrew Geweke)
  282. Date: Tue,  3 May 1994 20:56:35 -0400
  283. Organization: Michigan State University
  284.  
  285. In article <rmah-030594174155@rmah.dialup.access.net>, rmah@panix.com (Robert 
  286. S. Mah) writes:
  287. > Another option, since you only want integer aproximations, is to create 
  288. > a table of squares and do a binary search over it.  A 1000 element 
  289. > table will give you a range of 1->1,000,000 with an average of log2
  290. > (1000) = 10 lookups using a simple binary search.  A table with 32K or 
  291. > so elements will 
  292. >  
  293. > have a range of 1->1,000,000,000 and will be searchable in log2(32K) = 30 
  294. > lookups.  If you can spare a few dozen K, then this may be fast enough. 
  295.  
  296. Actually, I once found this algorithm:
  297.  
  298. int intSqrt (int num) {
  299.    for (i = j = 1, k = 3; num > j; j += (k+=2), ++i)
  300.           ;
  301.  
  302.    return i;
  303. }
  304.  
  305. Note that this algorithm rounds up, not down. I'm not sure exactly how 
  306. correct this is (I just coded it off the top of my head) but you get the 
  307. basic idea in any case. Adding the odd integers gives you the squares; i.e. 1 
  308. = 1; 1 + 3 = 4; 1 + 3 + 5 = 9; 1 + 3 + 5 + 7 = 16; 1 + 3 + 5 + 7 + 9 = 25; 
  309. and so on.
  310.  
  311. I don't know how fast this is in your specific instance, but it should be 
  312. quite fast.
  313.  
  314.  
  315.  
  316.  
  317.  
  318. +++++++++++++++++++++++++++
  319.  
  320. >From rmah@panix.com (Robert S. Mah)
  321. Date: Tue, 03 May 1994 22:04:22 -0500
  322. Organization: One Step Beyond
  323.  
  324. gewekean@studentg.msu.edu (Andrew Geweke) wrote:
  325.  
  326. > rmah@panix.com (Robert  S. Mah) writes:
  327. > > Another option, since you only want integer aproximations, is to create 
  328. > > a table of squares and do a binary search over it.  A 1000 element 
  329. > > [...]
  330. > > have a range of 1->1,000,000,000 and will be searchable in log2(32K) = 30 
  331. > > lookups.  If you can spare a few dozen K, then this may be fast enough. 
  332. > Actually, I once found this algorithm:
  333. > int intSqrt (int num) {
  334. >    for (i = j = 1, k = 3; num > j; j += (k+=2), ++i)
  335. >           ;
  336. >    return i;
  337. > }
  338. > Note that this algorithm rounds up, not down. I'm not sure exactly how 
  339. > correct this is (I just coded it off the top of my head) but you get the 
  340. > basic idea in any case. Adding the odd integers gives you the squares; 
  341. > i.e. 1  = 1; 1 + 3 = 4; 1 + 3 + 5 = 9; 1 + 3 + 5 + 7 = 16; 1 + 3 + 5 + 
  342. > 7 + 9 = 25;  and so on.
  343. > I don't know how fast this is in your specific instance, but it should  
  344. > be quite fast.
  345.  
  346. That's a great little algorithm!  That sequence looks _so_ familiar, but
  347. for the life of me, I can't recall the name...
  348.  
  349. Anyway, it looks like it would be order O(sqrt(n)) where n is the argument 
  350. to the function.  Only a problem if the domain range for the application 
  351. is large, that is Sqrt(10000) would take 10 times as long as Sqrt(100).  
  352. However, unlike the table method, the upper bounds isn't fixed at compile
  353. time.
  354.  
  355. Cheers,
  356. Rob
  357. ___________________________________________________________________________
  358. Robert S. Mah  -=-  One Step Beyond  -=-  212-947-6507  -=-  rmah@panix.com
  359.  
  360. +++++++++++++++++++++++++++
  361.  
  362. >From pottier@corvette.ens.fr (Francois Pottier)
  363. Date: 4 May 1994 09:42:29 GMT
  364. Organization: Ecole Normale Superieure, PARIS, France
  365.  
  366. In article <busfield.767985832@hurricane>,
  367. John D. Busfield <busfield@hurricane.seas.ucla.edu> wrote:
  368.  
  369. >    Does anyone have an algorithm or code for computing square roots.
  370.  
  371.  
  372. There was a thread on this subject about a year ago. Here's what
  373. I kept:
  374.  
  375. - -----------------------------------------------------------------------
  376.  
  377.  
  378. >Does somebody have code or an algorithm for extracting a long integer
  379. >square root and returning an integer?
  380.  
  381. There was a long series of letters in Dr.  Dobbs' Journal a few years
  382. back that I was a part of.  Here are two 'competing' subroutines for the
  383. 68000 that I wrote.  One is a Newton-Raphson iterator, the other a
  384. hybrid of three different subroutines using two different methods,
  385. heavily optimized for speed.  The non-Newton one is faster in some cases
  386. and slower in others.  Choosing one as 'best' depends on what kind of
  387. input ranges you expect to see most often.  Newton's time doesn't vary
  388. much on the average based on the input argument.  The non-Newton one
  389. ranges from a lot better (small arguments) to a little worse (large
  390. arguments), but is always better than Newton's worst case.  Don't
  391. neglect the fact that on a FPU-equipped machine it may be faster to use
  392. floating point.  I've done no research into this possibility, nor have I
  393. timed this stuff on any 68020+ system.  The speed balance is no doubt
  394. different then.  (For that matter, the 68000 testbed had no wait states
  395. nor interrupt system overhead, which doesn't necessarily apply to a
  396. 68000 PowerBook, and certainly doesn't apply to a Mac+ or earlier.)
  397.  
  398. I'm personally fond of the non-Newton version, because the algorithm
  399. only uses shifts and adds, so it could be implemented in microcode with
  400. about same speed as a divide.
  401.  
  402. *************************************************************************
  403. *                                                                       *
  404. *       Integer Square Root (32 to 16 bit).                             *
  405. *                                                                       *
  406. *       (Newton-Raphson method).                                        *
  407. *                                                                       *
  408. *       Call with:                                                      *
  409. *               D0.L = Unsigned number.                                 *
  410. *                                                                       *
  411. *       Returns:                                                        *
  412. *               D0.L = SQRT(D0.L)                                       *
  413. *                                                                       *
  414. *       Notes:  Result fits in D0.W, but is valid in longword.          *
  415. *               Takes from 338 cycles (1 shift, 1 division) to          *
  416. *               1580 cycles (16 shifts, 4 divisions)  (including rts).  *
  417. *               Averages 854 cycles measured over first 65535 roots.    *
  418. *               Averages 992 cycles measured over first 500000 roots.   *
  419. *                                                                       *
  420. *************************************************************************
  421.  
  422.         .globl lsqrt
  423. *                       Cycles
  424. lsqrt   movem.l d1-d2,-(sp) (24)
  425.         move.l d0,d1    (4)     ; Set up for guessing algorithm.
  426.         beq.s return    (10/8)  ; Don't process zero.
  427.         moveq #1,d2     (4)
  428.  
  429. guess   cmp.l d2,d1     (6)     ; Get a guess that is guaranteed to be
  430.         bls.s newton    (10/8)  ; too high, but not by much, by dividing the
  431.         add.l d2,d2     (8)     ; argument by two and multiplying a 1 by 2
  432.         lsr.l #1,d1     (10)    ; until the power of two passes the modified
  433.         bra.s guess     (10)    ; argument, then average these two numbers.
  434.  
  435. newton  add.l d1,d2     (8)     ; Average the two guesses.
  436.         lsr.l #1,d2     (10)
  437.         move.l d0,d1    (4)     ; Generate the next approximation(s)
  438.         divu d2,d1      (140)   ; via the Newton-Raphson method.
  439.         bvs.s done      (10/8)  ; Handle out-of-range input (cheats!)
  440.         cmp.w d1,d2     (4)     ; Have we converged?
  441.         bls.s done      (10/8)
  442.         swap d1         (4)     ; No, kill the remainder so the
  443.         clr.w d1        (4)     ; next average comes out right.
  444.         swap d1         (4)
  445.         bra.s newton    (10)
  446.  
  447. done    clr.w d0        (4)     ; Return a word answer in a longword.
  448.         swap d0         (4)
  449.         move.w d2,d0    (4)
  450. return  movem.l (sp)+,d1-d2  (28)
  451.         rts             (16)
  452.  
  453.         end
  454. *************************************************************************
  455. *                                                                       *
  456. *       Integer Square Root (32 to 16 bit).                             *
  457. *                                                                       *
  458. *       (Exact method, not approximate).                                *
  459. *                                                                       *
  460. *       Call with:                                                      *
  461. *               D0.L = Unsigned number.                                 *
  462. *                                                                       *
  463. *       Returns:                                                        *
  464. *               D0.L = SQRT(D0.L)                                       *
  465. *                                                                       *
  466. *       Notes:  Result fits in D0.W, but is valid in longword.          *
  467. *               Takes from 122 to 1272 cycles (including rts).          *
  468. *               Averages 610 cycles measured over first 65535 roots.    *
  469. *               Averages 1104 cycles measured over first 500000 roots.  *
  470. *                                                                       *
  471. *************************************************************************
  472.  
  473.         .globl lsqrt
  474. *                       Cycles
  475. lsqrt   tst.l d0        (4)     ; Skip doing zero.
  476.         beq.s done      (10/8)
  477.         cmp.l #$10000,d0 (14)   ; If is a longword, use the long routine.
  478.         bhs.s glsqrt    (10/8)
  479.         cmp.w #625,d0   (8)     ; Would the short word routine be quicker?
  480.         bhi.s gsqrt     (10/8)  ; No, use general purpose word routine.
  481. *                               ; Otherwise fall into special routine.
  482. *
  483. *  For speed, we use three exit points.
  484. *  This is cheesy, but this is a speed-optimized subroutine!
  485.  
  486.         page
  487. *************************************************************************
  488. *                                                                       *
  489. *       Faster Integer Square Root (16 to 8 bit).  For small arguments. *
  490. *                                                                       *
  491. *       (Exact method, not approximate).                                *
  492. *                                                                       *
  493. *       Call with:                                                      *
  494. *               D0.W = Unsigned number.                                 *
  495. *                                                                       *
  496. *       Returns:                                                        *
  497. *               D0.W = SQRT(D0.W)                                       *
  498. *                                                                       *
  499. *       Notes:  Result fits in D0.B, but is valid in word.              *
  500. *               Takes from 72 (d0=1) to 504 (d0=625) cycles             *
  501. *               (including rts).                                        *
  502. *                                                                       *
  503. *       Algorithm supplied by Motorola.                                 *
  504. *                                                                       *
  505. *************************************************************************
  506.  
  507. * Use the theorem that a perfect square is the sum of the first
  508. * sqrt(arg) number of odd integers.
  509.  
  510. *                       Cycles
  511.         move.w d1,-(sp) (8)
  512.         move.w #-1,d1   (8)
  513. qsqrt1  addq.w #2,d1    (4)
  514.         sub.w d1,d0     (4)
  515.         bpl qsqrt1      (10/8)
  516.         asr.w #1,d1     (8)
  517.         move.w d1,d0    (4)
  518.         move.w (sp)+,d1 (12)
  519. done    rts             (16)
  520.  
  521.         page
  522. *************************************************************************
  523. *                                                                       *
  524. *       Integer Square Root (16 to 8 bit).                              *
  525. *                                                                       *
  526. *       (Exact method, not approximate).                                *
  527. *                                                                       *
  528. *       Call with:                                                      *
  529. *               D0.W = Unsigned number.                                 *
  530. *                                                                       *
  531. *       Returns:                                                        *
  532. *               D0.L = SQRT(D0.W)                                       *
  533. *                                                                       *
  534. *       Uses:   D1-D4 as temporaries --                                 *
  535. *               D1 = Error term;                                        *
  536. *               D2 = Running estimate;                                  *
  537. *               D3 = High bracket;                                      *
  538. *               D4 = Loop counter.                                      *
  539. *                                                                       *
  540. *       Notes:  Result fits in D0.B, but is valid in word.              *
  541. *                                                                       *
  542. *               Takes from 544 to 624 cycles (including rts).           *
  543. *                                                                       *
  544. *               Instruction times for branch-type instructions          *
  545. *               listed as (X/Y) are for (taken/not taken).              *
  546. *                                                                       *
  547. *************************************************************************
  548.  
  549. *                       Cycles
  550. gsqrt   movem.l d1-d4,-(sp) (40)
  551.         move.w #7,d4    (8)     ; Loop count (bits-1 of result).
  552.         clr.w d1        (4)     ; Error term in D1.
  553.         clr.w d2        (4)
  554. sqrt1   add.w d0,d0     (4)     ; Get 2 leading bits a time and add
  555.         addx.w d1,d1    (4)     ; into Error term for interpolation.
  556.         add.w d0,d0     (4)     ; (Classical method, easy in binary).
  557.         addx.w d1,d1    (4)
  558.         add.w d2,d2     (4)     ; Running estimate * 2.
  559.         move.w d2,d3    (4)
  560.         add.w d3,d3     (4)
  561.         cmp.w d3,d1     (4)
  562.         bls.s sqrt2     (10/8)  ; New Error term > 2* Running estimate?
  563.         addq.w #1,d2    (4)     ; Yes, we want a '1' bit then.
  564.         addq.w #1,d3    (4)     ; Fix up new Error term.
  565.         sub.w d3,d1     (4)
  566. sqrt2   dbra d4,sqrt1   (10/14) ; Do all 8 bit-pairs.
  567.         move.w d2,d0    (4)
  568.         movem.l (sp)+,d1-d4 (44)
  569.         rts             (16)
  570.  
  571.         page
  572. *************************************************************************
  573. *                                                                       *
  574. *       Integer Square Root (32 to 16 bit).                             *
  575. *                                                                       *
  576. *       (Exact method, not approximate).                                *
  577. *                                                                       *
  578. *       Call with:                                                      *
  579. *               D0.L = Unsigned number.                                 *
  580. *                                                                       *
  581. *       Returns:                                                        *
  582. *               D0.L = SQRT(D0.L)                                       *
  583. *                                                                       *
  584. *       Uses:   D1-D4 as temporaries --                                 *
  585. *               D1 = Error term;                                        *
  586. *               D2 = Running estimate;                                  *
  587. *               D3 = High bracket;                                      *
  588. *               D4 = Loop counter.                                      *
  589. *                                                                       *
  590. *       Notes:  Result fits in D0.W, but is valid in longword.          *
  591. *                                                                       *
  592. *               Takes from 1080 to 1236 cycles (including rts.)         *
  593. *                                                                       *
  594. *               Two of the 16 passes are unrolled from the loop so that *
  595. *               quicker instructions may be used where there is no      *
  596. *               danger of overflow (in the early passes).               *
  597. *                                                                       *
  598. *               Instruction times for branch-type instructions          *
  599. *               listed as (X/Y) are for (taken/not taken).              *
  600. *                                                                       *
  601. *************************************************************************
  602.  
  603. *                       Cycles
  604. glsqrt  movem.l d1-d4,-(sp) (40)
  605.         moveq #13,d4    (4)     ; Loop count (bits-1 of result).
  606.         moveq #0,d1     (4)     ; Error term in D1.
  607.         moveq #0,d2     (4)
  608. lsqrt1  add.l d0,d0     (8)     ; Get 2 leading bits a time and add
  609.         addx.w d1,d1    (4)     ; into Error term for interpolation.
  610.         add.l d0,d0     (8)     ; (Classical method, easy in binary).
  611.         addx.w d1,d1    (4)
  612.         add.w d2,d2     (4)     ; Running estimate * 2.
  613.         move.w d2,d3    (4)
  614.         add.w d3,d3     (4)
  615.         cmp.w d3,d1     (4)
  616.         bls.s lsqrt2    (10/8)  ; New Error term > 2* Running estimate?
  617.         addq.w #1,d2    (4)     ; Yes, we want a '1' bit then.
  618.         addq.w #1,d3    (4)     ; Fix up new Error term.
  619.         sub.w d3,d1     (4)
  620. lsqrt2  dbra d4,lsqrt1  (10/14) ; Do first 14 bit-pairs.
  621.  
  622.         add.l d0,d0     (8)     ; Do 15-th bit-pair.
  623.         addx.w d1,d1    (4)
  624.         add.l d0,d0     (8)
  625.         addx.l d1,d1    (8)
  626.         add.w d2,d2     (4)
  627.         move.l d2,d3    (4)
  628.         add.w d3,d3     (4)
  629.         cmp.l d3,d1     (6)
  630.         bls.s lsqrt3    (10/8)
  631.         addq.w #1,d2    (4)
  632.         addq.w #1,d3    (4)
  633.         sub.l d3,d1     (8)
  634.  
  635. lsqrt3  add.l d0,d0     (8)     ; Do 16-th bit-pair.
  636.         addx.l d1,d1    (8)
  637.         add.l d0,d0     (8)
  638.         addx.l d1,d1    (8)
  639.         add.w d2,d2     (4)
  640.         move.l d2,d3    (4)
  641.         add.l d3,d3     (8)
  642.         cmp.l d3,d1     (6)
  643.         bls.s lsqrt4    (10/8)
  644.         addq.w #1,d2    (4)
  645. lsqrt4  move.w d2,d0    (4)
  646.         movem.l (sp)+,d1-d4 (44)
  647.         rts             (16)
  648.  
  649.         end
  650. -- 
  651. +----------------+
  652. ! II      CCCCCC !  Jim Cathey
  653. ! II  SSSSCC     !  ISC-Bunker Ramo
  654. ! II      CC     !  TAF-C8;  Spokane, WA  99220
  655. ! IISSSS  CC     !  UUCP: uunet!isc-br!jimc (jimc@isc-br.isc-br.com)
  656. ! II      CCCCCC !  (509) 927-5757
  657. +----------------+
  658.  
  659. - -----------------------------------------------------------------------------
  660.  
  661. /*
  662.  * ISqrt--
  663.  *     Find square root of n.  This is a Newton's method approximation,
  664.  * converging in 1 iteration per digit or so.  Finds floor(sqrt(n) + 0.5).
  665.  */
  666. int ISqrt(register int n)
  667. {
  668.     register int i;
  669.     register long k0, k1, nn;
  670.  
  671.     for (nn = i = n, k0 = 2; i > 0; i >>= 2, k0 <<= 1)
  672.         ;
  673.     nn <<= 2;
  674.     for (;;) {
  675.         k1 = (nn / k0 + k0) >> 1;
  676.         if (((k0 ^ k1) & ~1) == 0)
  677.             break;
  678.         k0 = k1;
  679.     }
  680.     return (int) ((k1 + 1) >> 1);    
  681. }
  682.  
  683. -- 
  684. Joseph Nathan Hall  |  Joseph's Rule of Thumb: Most folks aren't interested
  685. Software Architect  |                          in your rules of thumb.
  686. Gorca Systems Inc.  |  ----- joseph@joebloe.maple-shade.nj.us (home) -----
  687. (on assignment)     |        (602) 732-2549 jnhall@sat.mot.com (work)
  688.  
  689. - -----------------------------------------------------------------------------
  690.  
  691. Here's an article I saved from c.s.m.p four months ago.  Strangely, it
  692. was only distributed in North America.  I don't know how fast it works
  693. in practice, but there are no multiplications or divisions in its inner
  694. loop, which is promising.
  695.  
  696.  
  697. #include <math.h>
  698.  
  699. /*
  700.  * It requires more space to describe this implementation of the manual
  701.  * square root algorithm than it did to code it.  The basic idea is that
  702.  * the square root is computed one bit at a time from the high end.  Because
  703.  * the original number is 32 bits (unsigned), the root cannot exceed 16 bits
  704.  * in length, so we start with the 0x8000 bit.
  705.  *
  706.  * Let "x" be the value whose root we desire, "t" be the square root
  707.  * that we desire, and "s" be a bitmask.  A simple way to compute
  708.  * the root is to set "s" to 0x8000, and loop doing the following:
  709.  *
  710.  *    t = 0;
  711.  *    s = 0x8000;
  712.  *    do {
  713.  *        if ((t + s) * (t + s) <= x)
  714.  *            t += s;
  715.  *        s >>= 1;
  716.  *    while (s != 0);
  717.  *
  718.  * The primary disadvantage to this approach is the multiplication.  To
  719.  * eliminate this, we begin simplying.  First, we observe that
  720.  *
  721.  *    (t + s) * (t + s) == (t * t) + (2 * t * s) + (s * s)
  722.  *
  723.  * Therefore, if we redefine "x" to be the original argument minus the
  724.  * current value of (t * t), we can determine if we should add "s" to
  725.  * the root if
  726.  *
  727.  *    (2 * t * s) + (s * s) <= x
  728.  *
  729.  * If we define a new temporary "nr", we can express this as
  730.  *
  731.  *    t = 0;
  732.  *    s = 0x8000;
  733.  *    do {
  734.  *        nr = (2 * t * s) + (s * s);
  735.  *        if (nr <= x) {
  736.  *            x -= nr;
  737.  *            t += s;
  738.  *        }
  739.  *        s >>= 1;
  740.  *    while (s != 0);
  741.  *
  742.  * We can improve the performance of this by noting that "s" is always a
  743.  * power of two, so multiplication by "s" is just a shift.  Also, because
  744.  * "s" changes in a predictable manner (shifted right after each iteration)
  745.  * we can precompute (0x8000 * t) and (0x8000 * 0x8000) and then adjust
  746.  * them by shifting after each step.  First, we let "m" hold the value
  747.  * (s * s) and adjust it after each step by shifting right twice.  We
  748.  * also introduce "r" to hold (2 * t * s) and adjust it after each step
  749.  * by shifting right once.  When we update "t" we must also update "r",
  750.  * and we do so by noting that (2 * (old_t + s) * s) is the same as
  751.  * (2 * old_t * s) + (2 * s * s).  Noting that (s * s) is "m" and that
  752.  * (r + 2 * m) == ((r + m) + m) == (nr + m):
  753.  *
  754.  *    t = 0;
  755.  *    s = 0x8000;
  756.  *    m = 0x40000000;
  757.  *    r = 0;
  758.  *    do {
  759.  *        nr = r + m;
  760.  *        if (nr <= x) {
  761.  *            x -= nr;
  762.  *            t += s;
  763.  *            r = nr + m;
  764.  *        }
  765.  *        s >>= 1;
  766.  *        r >>= 1;        
  767.  *        m >>= 2;
  768.  *    } while (s != 0);
  769.  *
  770.  * Finally, we note that, if we were using fractional arithmetic, after
  771.  * 16 iterations "s" would be a binary 0.5, so the value of "r" when
  772.  * the loop terminates is (2 * t * 0.5) or "t".  Because the values in
  773.  * "t" and "r" are identical after the loop terminates, and because we
  774.  * do not otherwise use "t"  explicitly within the loop, we can omit it.
  775.  * When we do so, there is no need for "s" except to terminate the loop,
  776.  * but we observe that "m" will become zero at the same time as "s",
  777.  * so we can use it instead.
  778.  *
  779.  * The result we have at this point is the floor of the square root.  If
  780.  * we want to round to the nearest integer, we need to consider whether
  781.  * the remainder in "x" is greater than or equal to the difference
  782.  * between ((r + 0.5) * (r + 0.5)) and (r * r).  Noting that the former
  783.  * quantity is (r * r + r + 0.25), we want to check if the remainder is
  784.  * greater than or equal to (r + 0.25).  Because we are dealing with
  785.  * integers, we can't have equality, so we round up if "x" is strictly
  786.  * greater than "r":
  787.  *
  788.  *    if (x > r)
  789.  *        r++;
  790.  */
  791.  
  792. unsigned int isqrt(unsigned long x)
  793. {
  794.     unsigned long r, nr, m;
  795.  
  796.     r = 0;
  797.     m = 0x40000000;
  798.     do {
  799.         nr = r + m;
  800.         if (nr <= x) {
  801.             x -= nr;
  802.             r = nr + m;
  803.         }
  804.         r >>= 1;
  805.         m >>= 2;
  806.     } while (m != 0);
  807.  
  808.     if (x > r)
  809.         r++;
  810.     return(r);
  811. }
  812. --
  813. (Dr.) John Bruner, Deputy Director            bruner@csrd.uiuc.edu
  814. Center for Supercomputing Research & Development    (217) 244-4476 (voice)
  815. University of Illinois at Urbana-Champaign        (217) 244-1351 (FAX)
  816. 465 CSRL, MC-264; 1308 West Main St.; Urbana, IL  61801-2307
  817.  
  818.  
  819. -- 
  820.  Jamie McCarthy        Internet: k044477@kzoo.edu    AppleLink: j.mccarthy
  821.  
  822. - -----------------------------------------------------------------------------
  823.  
  824. Then there is the easy way - use the toolbox:
  825.  
  826. #define LongSqrt(x) ((short)(FracSqrt((Fract)(x)) >> 15))
  827.  
  828. FractSqrt is in FixMath.h. This works because given two fixed point number 
  829. of the form x.y, where x is the number of bits before the decimal point 
  830. and y is the number of bits after the decimal point, twos complement 
  831. multiplication will yield a result of: x1.y1 * x2.y2 = x1+x2.y1+y2. If the 
  832. numbers are the same format, this becomes x.y * x.y = 2x.2y. This holds 
  833. for squaring a number also: x.y^2 = 2x.2y. The sqrt is then sqrt(x.y) = 
  834. x/2.y/2. FracSqrt is of the form FracSqrt(2.30) = 2.30. Since we know how 
  835. sqrt works this can also be expressed as FracSqrt(x.y) = x/2.y/2 << 15 
  836. (This is a "virtual" shift since the calculation is compleated with more 
  837. precision the 15 bits shifted in are "real" and not 0). So if you want to 
  838. use FracSqrt for a long you get FracSqrt(32.0) = 16.0 << 15. So you shift 
  839. the result down be 15 to get a short (you can add 1 << 14 prior to 
  840. shifting down by 15 to round instead of truncing your result). If you 
  841. wanted a long sqrt with a 16.16 (Fixed) result you would use:
  842.  
  843. #define LongFixedSqrt(x) ((Fixed)(FracSqrt((Fract)(x)) << 1))
  844.  
  845. If you want a Fixed (16.16) sqrt with a Fixed result (16.16) you would use:
  846.  
  847. #define FixedSqrt(x) ((Fixed)FracSqrt((Fract)(x)) >> 7))
  848.  
  849. You can do this kind of work with all of the fixed point routines and 
  850. standard operators.
  851.  
  852. Sean Parent
  853.  
  854.  
  855.  
  856. -- 
  857. Francois Pottier                                            pottier@dmi.ens.fr
  858. - ----------------------------------------------------------------------------
  859. This area dedicated to the preservation of endangered species.         "Moof!"
  860.  
  861. +++++++++++++++++++++++++++
  862.  
  863. >From christer@cs.umu.se (Christer Ericson)
  864. Date: Wed, 4 May 1994 12:16:40 GMT
  865. Organization: Dept. of Computing Science, Umea Univ., 901 87 Umea, Sweden
  866.  
  867. In <busfield.767985832@hurricane> busfield@hurricane.seas.ucla.edu (John D. Busfield) writes:
  868.  
  869. >    Does anyone have an algorithm or code for computing square roots.
  870. >The emphasis is on speed rather than accuracy in that I only need the
  871. >result rounded to the nearest integer (ie sqrt(1000) = 31 or 32).
  872. >Thanks in advance.
  873.  
  874. I posted this to comp.sys.m68k some time ago, here it is again:
  875.  
  876.  
  877. unsigned short ce_quick_sqrt(n)
  878. register unsigned long n;
  879. {
  880.     asm {
  881. ;-------------------------
  882. ;
  883. ; Routine       : ISQRT; integer square root
  884. ; I/O parameters: d0.w = sqrt(d0.l)
  885. ; Registers used: d0-d2/a0
  886. ;
  887. ; This is a highly optimized integer square root routine, based
  888. ; on the iterative Newton/Babylonian method
  889. ;
  890. ;    r(n + 1) = (r(n) + A / R(n)) / 2
  891. ;
  892. ; Verified over the full interval [0x0L,0xFFFFFFFFL]
  893. ;
  894. ; Some minor compromises have been made to make it perform well
  895. ; on the 68000 as well as 68020/030/040. This routine outperforms
  896. ; the best of all other algorithms I've seen (except for a table
  897. ; lookup).
  898. ;
  899. ; Copyright (c) Christer Ericson, 1993. All rights reserved.
  900. ;
  901. ; Christer Ericson, Dept. of Computer Science, University of Umea,
  902. ; S-90187 UMEA, SWEDEN. Internet: christer@cs.umu.se
  903. ;
  904.  
  905. ;-------------------------
  906. ;
  907. ; Macintosh preamble since THINK C passes first register param
  908. ; in d7. Remove this section on any other machine
  909. ;
  910.     move.l    d7,d0
  911. ;-------------------------
  912. ;
  913. ; Actual integer square root routine starts here
  914. ;
  915.     move.l    d0,a0        ; save original input value for the iteration
  916.     beq.s    @exit        ; unfortunately we must special case zero
  917.     moveq    #2,d1        ; init square root guess
  918. ;-------------------------
  919. ;
  920. ; Speed up the process of finding a power of two approximation
  921. ; to the actual square root by shifting an appropriate amount
  922. ; when the input value is large enough
  923. ;
  924. ; If input values are word only, this section can be removed
  925. ;
  926.     move.l    d0,d2
  927.     swap    d2        ; do [and.l 0xFFFF0000,d2] this way to...
  928.     tst.w    d2        ; go faster on 68000 and to avoid having to...
  929.     beq.s    @skip8        ; reload d2 for the next test below
  930.     move.w    #0x200,d1    ; faster than lsl.w #8,d1 (68000)
  931.     lsr.l    #8,d0
  932. @skip8    and.w    #0xFE00,d2    ; this value and shift by 5 are magic
  933.     beq.s    @skip4
  934.     lsl.w    #5,d1
  935.     lsr.l    #5,d0
  936. @skip4
  937.  
  938. ;-------------------------
  939. ;
  940. ; This finds the power of two approximation to the actual square root
  941. ; by doing the integer equivalent to sqrt(x) = 2 ^ (log2(x) / 2). This
  942. ; is done by shifting the input value down while shifting the root
  943. ; approximation value up until they meet in the middle. Better precision
  944. ; (in the step described below) is gained by starting the approximation
  945. ; at 2 instead of 1 (this means that the approximation will be a power
  946. ; of two too large so remember to shift it down).
  947. ;
  948. ; Finally (and here's the clever thing) since, by previously shifting the
  949. ; input value down, it has actually been divided by the root approximation
  950. ; value already so the first iteration is "for free". Not bad, eh?
  951. ;
  952. @loop    add.l    d1,d1
  953.     lsr.l    #1,d0
  954.     cmp.l    d0,d1
  955.     bcs.s    @loop
  956. @skip    lsr.l    #1,d1        ; adjust the approximation
  957.     add.l    d0,d1        ; here we just add and shift to...
  958.     lsr.l    #1,d1        ; get the first iteration "for free"!
  959. ;-------------------------
  960. ;
  961. ; The iterative root value is guaranteed to be larger than (or equal to)
  962. ; the actual square root, except for the initial guess. But since the first
  963. ; iteration was done above, the loop test can be simplified below
  964. ; (Oh, without the bvs.s the routine will fail on most large numbers, like
  965. ; for instance, 0xFFFF0000. Could there be a better way of handling these,
  966. ; so the bvs.s can be removed? Nah...)
  967. ;
  968. @loop2    move.l    a0,d2        ; get original input value
  969.     move.w    d1,d0        ; save current guess
  970.     divu.w    d1,d2        ; do the Newton method thing
  971.     bvs.s    @exit        ; if div overflows, exit with current guess
  972.     add.w    d2,d1
  973.     roxr.w    #1,d1        ; roxr ensures shifting back carry overflow
  974.     cmp.w    d0,d1
  975.     bcs.s    @loop2        ; exit with result in d0.w
  976. @exit
  977.     }
  978. }
  979.  
  980.  
  981. Christer Ericson --- Internet: christer@cs.umu.se --- tel: +46-90-166794
  982. Department of Computer Science, University of Umea, S-90187 UMEA, SWEDEN
  983.  
  984. +++++++++++++++++++++++++++
  985.  
  986. >From usenet@lowry.eche.ualberta.ca (Brian Lowry)
  987. Date: 4 May 1994 16:38:23 GMT
  988. Organization: Dept. of Chemical Eng., University of Alberta
  989.  
  990. Well, if people are going to start posting square root routines that use
  991. division, here's about the simplest possible, coded in C:
  992.  
  993.  
  994. #define precLim 1e-8   //for good single precision performance
  995.  
  996. float sqrt(float x);
  997.  
  998. float sqrt(float x)
  999. {    register float d = 0.5*(1.0 - x);
  1000.         register float b = 1.0 - d;
  1001.     
  1002.     while ((d > precLim)||(d < precLim))
  1003.     {    d *= 0.5*d/b; b -= d;}
  1004.  
  1005.     return b;
  1006. }
  1007.  
  1008.  
  1009.   This takes about three to five iterations, but on the PowerPC that
  1010. amounts to a whopping 100 to 170 clock cycles.  Since that's enough cycles
  1011. for about 80 multiplies and/or flops, division is definitely not the best
  1012. route here (though it's certainly compact...)
  1013.  
  1014. Brian Lowry
  1015.  
  1016. +++++++++++++++++++++++++++
  1017.  
  1018. >From parkb@bigbang.Stanford.EDU (Brian Park)
  1019. Date: 4 May 1994 20:43:37 GMT
  1020. Organization: Stanford University
  1021.  
  1022. I am assuming that the original poster wanted integer in/ integer out
  1023. since he only wanted accurary within 1.
  1024.  
  1025. The following is a description of code which follows at the end of this
  1026. article.
  1027.  
  1028. lsqrt2() - traditional Newton's method
  1029. - ------
  1030. The traditional Newton's method of getting y = sqrt(n), coded as lsqrt2()
  1031. below)
  1032.  
  1033.     n = y^2
  1034.     y(0) = n
  1035.     y(i+1) = (y(i) + n/y(i))/2
  1036.  
  1037. is second-order convergent, meaning that the relative error in the i+1
  1038. iteration is proportional to the square of the previous error
  1039. (remember, at sufficiently large iteration, relative error << 1).  [Do
  1040. a Taylor series exansion to verify that the first order term
  1041. vanishes].  Hence, for a fixed tolerance, in this case, within unity
  1042. (ie. error of 1/n), the algorithm performs a bisection on the
  1043. error at every iteration.
  1044.  
  1045. My point is that Newton's method is O(log_2(n)) and you are not going
  1046. to do much better than that.  Binary lookup tables are O(log_2(n)) 
  1047. efficient.  The only thing you might save is an integer division
  1048. compared to the Newton's method (see n/y(i) above).  But it also globbles
  1049. up memory and has fixed size.  A hash table provides the fastest
  1050. lookup table, but it takes up even more memory than the binary lookup
  1051. table, and coding it can be more tricky.  Do you really want to use up
  1052. that much memory for a simple square root function?
  1053.  
  1054. I should add that Newton's method is guaranteed to converge for all n.
  1055.  
  1056. lsqrt1() - bit-shift method
  1057. - -----
  1058. There is yet another method (see lsqrt1() function below) that I dreamed
  1059. up last night, and coded it quickly this morning.  It uses bit-shifts
  1060. to perform an integer square root by taking log_2(n), dividing it
  1061. by 2 (hence doing a square root) and shifting it back.  This routine is
  1062. also O(log_2(n)) but has the peculiar property that it is _faster_
  1063. for larger numbers.  You can see why below.  It has the disadvantage that
  1064. it is quite inaccurate for small numbers, but surprisingly accurate for 
  1065. large numbers.
  1066.  
  1067. lsqrt3() - combination
  1068. - ------
  1069. If you really need accurary within unity, then you can plug the result
  1070. of the bit-shift method, lsqrt1(), use it as the initial guess for
  1071. the Newton's method and converge the answer down to its limiting
  1072. accurary.  This combination is really really fast, since Newton's
  1073. method converges within an iteration or two when the initial guess is
  1074. very close to the actual answer.  This has been coded as lsqrt3()
  1075. below.
  1076.  
  1077. For comparision, the straight Newton's method takes longer
  1078. because its initial guess is simply the original answer, n.
  1079. But let me empasize that even with straight Newton's method is O(log_2(n)),
  1080. Sqrt(10^9) takes only 19 iterations, as you can verify.  That's only 19
  1081. integer divisions.  How fast do you want your square root to be?
  1082.  
  1083. I have even more ideas on how to speed things up, but I think the code
  1084. below should get you going.  I'm sorry it's not coded in Macintosh,
  1085. I'm on the Unix box right now, and my mac's at home.  It hasn't
  1086. been tested extensively on the boundary points (ie. 0,1, 2^32-1), 
  1087. but you can do that.
  1088.  
  1089. My final comment concerns the O(sqrt(n)) algorithm that was posted
  1090. a short while ago.  Although it is simple and cute, I would not recommend
  1091. it when you have so many O(log_2(n)) routines to choose from.
  1092.  
  1093. Regards,
  1094. Brian Park
  1095.  
  1096. - - cut for code below ---
  1097.  
  1098. #include <stdio.h>
  1099.  
  1100. #define BITSIZE (sizeof(unsigned long)*8)
  1101.  
  1102. unsigned long lsqrtng();
  1103. unsigned long lsqrt1();
  1104. unsigned long lsqrt2();
  1105. unsigned long lsqrt3();
  1106.  
  1107. /***
  1108. Usage: 
  1109.     lsqrt n
  1110.  
  1111. Example:
  1112.  
  1113. lsqrt 100000
  1114. l = 1000000
  1115. bit shift: 976
  1116. iter = 13
  1117. newton: 1000
  1118. iter = 2
  1119. bit shift + newton: 1000
  1120. ***/
  1121. main(int argc, char **argv)
  1122. {
  1123.     unsigned long l;
  1124.  
  1125.     l = atol(argv[1]);
  1126.     printf("l = %lu\n", l);
  1127.  
  1128.     printf("bit shift: %lu\n", lsqrt1(l));
  1129.     printf("newton: %lu\n", lsqrt2(l));
  1130.     printf("bit shift + newton: %lu\n", lsqrt3(l));
  1131. }
  1132.  
  1133. /***
  1134. Take square root by performing bit-shifts, getting the log_2(a),
  1135. dividing by 2, and shifting back.
  1136. ***/
  1137. unsigned long lsqrt1(unsigned long a)
  1138. {
  1139.     register unsigned int i;
  1140.     register unsigned long l = a;
  1141.  
  1142.     if (a==0) return 0;
  1143.  
  1144.     for (i=0; l<(unsigned long)(1L<<(BITSIZE-1)) && i<BITSIZE; ++i)
  1145.         l<<=1;
  1146.  
  1147.     i = (32-i)>>1;
  1148.     a >>= i;
  1149.     return a;
  1150. }
  1151.  
  1152. /***
  1153. Take square root by using Newton's method with an initial guess of itself.
  1154. ***/
  1155. unsigned long lsqrt2(unsigned long a)
  1156. {
  1157.     return lsqrtng(a, a);
  1158. }
  1159.  
  1160. /***
  1161. Newton's method with guess.
  1162. Newton's method is second order convergence, hence it should be very fast.
  1163. ***/
  1164. unsigned long lsqrtng(register unsigned long a, unsigned long guess)
  1165. {
  1166.     register unsigned long b, b0;
  1167.     int i = 0;
  1168.  
  1169.     if (a == 0) return 0;
  1170.  
  1171.     b = guess;
  1172.     b0 = a/b;
  1173.     while (labs(b-b0)>1) {
  1174.         /* printf("guess = %lu\n", b);*/
  1175.         ++i;
  1176.         b0 = b;
  1177.         b=(a/b+b)>>1;
  1178.     }
  1179.     printf("iter = %d\n", i);
  1180.     return b;
  1181. }
  1182.  
  1183. /***
  1184. Combination Newton's method and bit-shifts.
  1185. ***/
  1186. unsigned long lsqrt3(unsigned long a)
  1187. {
  1188.     return lsqrtng(a, lsqrt1(a));
  1189. }
  1190.  
  1191. +++++++++++++++++++++++++++
  1192.  
  1193. >From sparent@mv.us.adobe.com (Sean Parent)
  1194. Date: Wed, 4 May 1994 20:46:30 GMT
  1195. Organization: Adobe Systems Incorporated
  1196.  
  1197. In article <9405032056.AA35937@geweke.ppp.msu.edu>,
  1198. gewekean@studentg.msu.edu (Andrew Geweke) wrote:
  1199.  
  1200. > Actually, I once found this algorithm:
  1201. > int intSqrt (int num) {
  1202. >    for (i = j = 1, k = 3; num > j; j += (k+=2), ++i)
  1203. >           ;
  1204. >    return i;
  1205. > }
  1206.  
  1207. This is a difference algorithim and similar algorithms can be used to solve
  1208. most any polynomial expression. This is the method used by Charles Babage
  1209. (sp?) in the late 1800's in his difference engine. For example: y = x^3 can
  1210. be calculated over a range with a given step in x of n by:
  1211.  
  1212. y = y` + a
  1213.  
  1214. Where a = (x + n)^3 - x^3. Or a = 3nx^2 + 3xn^2 + n^3.
  1215.  
  1216. The x^2 term (i) can be similary reduce:
  1217. i = i` + b
  1218. Where b = (x + n)^2 - x^2. Or b = 2xn + n^2.
  1219.  
  1220. Finaly the x term is reduced as:
  1221. x = x` + n
  1222.  
  1223. This can be coded up as a loop consisting of only additions. As to the
  1224. original question. To calculate a square root of an integer on a Mac, I
  1225. would code it as:
  1226.  
  1227. inline long LongSqrt(long x)
  1228. {
  1229.   return FracSqrt(x) >> 15;
  1230. }
  1231.  
  1232. FracSqrt is in FixMath.h. This works because squaring a fixed point number
  1233. doubles the number of fractional bits (so a number of type Fract, which is
  1234. 2d30 multiplied by a Fract would yield a 4d60 number). Taking the square
  1235. root of a number then halves the number of bits (to the original
  1236. precision). So a strait square root of a fract would yield a 1d15 value.
  1237. Apple's FracSqrt return a Fract so in effect it is calculating sqrt(x) <<
  1238. 15 [with the bits shifted in actually being calculated]. So if you want a
  1239. number of type Fixed as a result for the sqrt of an integer you could use.
  1240.  
  1241. inline Fixed FixedSqrtLong(long x)
  1242. {
  1243.      return FracSqrt(x) << 1;  // 0/2 + 15 + 1 = 16
  1244. }
  1245.  
  1246. Or a the sqrt of a Fixed yielding a fixed is:
  1247.  
  1248. inline Fixed FixedSqrt(Fixed x)
  1249. {
  1250.   return FracSqrt(x) >> 7; // 16/2 + 15 - 7 = 16
  1251. }
  1252.  
  1253. This is a difficult thing to explain, I don't no of any good terminology
  1254. for talking about fixed point numbers. Play with it some and it will make
  1255. sense.
  1256.  
  1257. -- 
  1258. Sean Parent
  1259.  
  1260. +++++++++++++++++++++++++++
  1261.  
  1262. >From jimc@tau-ceti.isc-br.com (Jim Cathey)
  1263. Date: Wed, 4 May 1994 18:04:33 GMT
  1264. Organization: Olivetti North America, Spokane, WA
  1265.  
  1266. In article <busfield.767985832@hurricane> busfield@hurricane.seas.ucla.edu (John D. Busfield) writes:
  1267. >    Does anyone have an algorithm or code for computing square roots.
  1268. >The emphasis is on speed rather than accuracy in that I only need the
  1269. >result rounded to the nearest integer (ie sqrt(1000) = 31 or 32).
  1270.  
  1271. Here's two:  A Newton's Method, and a cool bit-banger that's a little
  1272. faster under certain circumstances.  (Timings were all on a 68000
  1273. as these are kinda old.  Re-test to see what works best now.)
  1274.  
  1275. *************************************************************************
  1276. *                                                                       *
  1277. *       Integer Square Root (32 to 16 bit).                             *
  1278. *                                                                       *
  1279. *       (Newton-Raphson method).                                        *
  1280. *                                                                       *
  1281. *       Call with:                                                      *
  1282. *               D0.L = Unsigned number.                                 *
  1283. *                                                                       *
  1284. *       Returns:                                                        *
  1285. *               D0.L = SQRT(D0.L)                                       *
  1286. *                                                                       *
  1287. *       Notes:  Result fits in D0.W, but is valid in longword.          *
  1288. *               Takes from 338 cycles (1 shift, 1 division) to          *
  1289. *               1580 cycles (16 shifts, 4 divisions)  (including rts).  *
  1290. *               Averages 854 cycles measured over first 65535 roots.    *
  1291. *               Averages 992 cycles measured over first 500000 roots.   *
  1292. *                                                                       *
  1293. *************************************************************************
  1294.  
  1295.         .globl lsqrt
  1296. *                       Cycles
  1297. lsqrt   movem.l d1-d2,-(sp) (24)
  1298.         move.l d0,d1    (4)     ; Set up for guessing algorithm.
  1299.         beq.s return    (10/8)  ; Don't process zero.
  1300.         moveq #1,d2     (4)
  1301.  
  1302. guess   cmp.l d2,d1     (6)     ; Get a guess that is guaranteed to be
  1303.         bls.s newton    (10/8)  ; too high, but not by much, by dividing the
  1304.         add.l d2,d2     (8)     ; argument by two and multiplying a 1 by 2
  1305.         lsr.l #1,d1     (10)    ; until the power of two passes the modified
  1306.         bra.s guess     (10)    ; argument, then average these two numbers.
  1307.  
  1308. newton  add.l d1,d2     (8)     ; Average the two guesses.
  1309.         lsr.l #1,d2     (10)
  1310.         move.l d0,d1    (4)     ; Generate the next approximation(s)
  1311.         divu d2,d1      (140)   ; via the Newton-Raphson method.
  1312.         bvs.s done      (10/8)  ; Handle out-of-range input (cheats!)
  1313.         cmp.w d1,d2     (4)     ; Have we converged?
  1314.         bls.s done      (10/8)
  1315.         swap d1         (4)     ; No, kill the remainder so the
  1316.         clr.w d1        (4)     ; next average comes out right.
  1317.         swap d1         (4)
  1318.         bra.s newton    (10)
  1319.  
  1320. done    clr.w d0        (4)     ; Return a word answer in a longword.
  1321.         swap d0         (4)
  1322.         move.w d2,d0    (4)
  1323. return  movem.l (sp)+,d1-d2  (28)
  1324.         rts             (16)
  1325.  
  1326.         end
  1327. *************************************************************************
  1328. *                                                                       *
  1329. *       Integer Square Root (32 to 16 bit).                             *
  1330. *                                                                       *
  1331. *       (Exact method, not approximate).                                *
  1332. *                                                                       *
  1333. *       Call with:                                                      *
  1334. *               D0.L = Unsigned number.                                 *
  1335. *                                                                       *
  1336. *       Returns:                                                        *
  1337. *               D0.L = SQRT(D0.L)                                       *
  1338. *                                                                       *
  1339. *       Notes:  Result fits in D0.W, but is valid in longword.          *
  1340. *               Takes from 122 to 1272 cycles (including rts).          *
  1341. *               Averages 610 cycles measured over first 65535 roots.    *
  1342. *               Averages 1104 cycles measured over first 500000 roots.  *
  1343. *                                                                       *
  1344. *************************************************************************
  1345.  
  1346.         .globl lsqrt
  1347. *                       Cycles
  1348. lsqrt   tst.l d0        (4)     ; Skip doing zero.
  1349.         beq.s done      (10/8)
  1350.         cmp.l #$10000,d0 (14)   ; If is a longword, use the long routine.
  1351.         bhs.s glsqrt    (10/8)
  1352.         cmp.w #625,d0   (8)     ; Would the short word routine be quicker?
  1353.         bhi.s gsqrt     (10/8)  ; No, use general purpose word routine.
  1354. *                               ; Otherwise fall into special routine.
  1355. *
  1356. *  For speed, we use three exit points.
  1357. *  This is cheesy, but this is a speed-optimized subroutine!
  1358.  
  1359.         page
  1360. *************************************************************************
  1361. *                                                                       *
  1362. *       Faster Integer Square Root (16 to 8 bit).  For small arguments. *
  1363. *                                                                       *
  1364. *       (Exact method, not approximate).                                *
  1365. *                                                                       *
  1366. *       Call with:                                                      *
  1367. *               D0.W = Unsigned number.                                 *
  1368. *                                                                       *
  1369. *       Returns:                                                        *
  1370. *               D0.W = SQRT(D0.W)                                       *
  1371. *                                                                       *
  1372. *       Notes:  Result fits in D0.B, but is valid in word.              *
  1373. *               Takes from 72 (d0=1) to 504 (d0=625) cycles             *
  1374. *               (including rts).                                        *
  1375. *                                                                       *
  1376. *       Algorithm supplied by Motorola.                                 *
  1377. *                                                                       *
  1378. *************************************************************************
  1379.  
  1380. * Use the theorem that a perfect square is the sum of the first
  1381. * sqrt(arg) number of odd integers.
  1382.  
  1383. *                       Cycles
  1384.         move.w d1,-(sp) (8)
  1385.         move.w #-1,d1   (8)
  1386. qsqrt1  addq.w #2,d1    (4)
  1387.         sub.w d1,d0     (4)
  1388.         bpl qsqrt1      (10/8)
  1389.         asr.w #1,d1     (8)
  1390.         move.w d1,d0    (4)
  1391.         move.w (sp)+,d1 (12)
  1392. done    rts             (16)
  1393.  
  1394.         page
  1395. *************************************************************************
  1396. *                                                                       *
  1397. *       Integer Square Root (16 to 8 bit).                              *
  1398. *                                                                       *
  1399. *       (Exact method, not approximate).                                *
  1400. *                                                                       *
  1401. *       Call with:                                                      *
  1402. *               D0.W = Unsigned number.                                 *
  1403. *                                                                       *
  1404. *       Returns:                                                        *
  1405. *               D0.L = SQRT(D0.W)                                       *
  1406. *                                                                       *
  1407. *       Uses:   D1-D4 as temporaries --                                 *
  1408. *               D1 = Error term;                                        *
  1409. *               D2 = Running estimate;                                  *
  1410. *               D3 = High bracket;                                      *
  1411. *               D4 = Loop counter.                                      *
  1412. *                                                                       *
  1413. *       Notes:  Result fits in D0.B, but is valid in word.              *
  1414. *                                                                       *
  1415. *               Takes from 544 to 624 cycles (including rts).           *
  1416. *                                                                       *
  1417. *               Instruction times for branch-type instructions          *
  1418. *               listed as (X/Y) are for (taken/not taken).              *
  1419. *                                                                       *
  1420. *************************************************************************
  1421.  
  1422. *                       Cycles
  1423. gsqrt   movem.l d1-d4,-(sp) (40)
  1424.         move.w #7,d4    (8)     ; Loop count (bits-1 of result).
  1425.         clr.w d1        (4)     ; Error term in D1.
  1426.         clr.w d2        (4)
  1427. sqrt1   add.w d0,d0     (4)     ; Get 2 leading bits a time and add
  1428.         addx.w d1,d1    (4)     ; into Error term for interpolation.
  1429.         add.w d0,d0     (4)     ; (Classical method, easy in binary).
  1430.         addx.w d1,d1    (4)
  1431.         add.w d2,d2     (4)     ; Running estimate * 2.
  1432.         move.w d2,d3    (4)
  1433.         add.w d3,d3     (4)
  1434.         cmp.w d3,d1     (4)
  1435.         bls.s sqrt2     (10/8)  ; New Error term > 2* Running estimate?
  1436.         addq.w #1,d2    (4)     ; Yes, we want a '1' bit then.
  1437.         addq.w #1,d3    (4)     ; Fix up new Error term.
  1438.         sub.w d3,d1     (4)
  1439. sqrt2   dbra d4,sqrt1   (10/14) ; Do all 8 bit-pairs.
  1440.         move.w d2,d0    (4)
  1441.         movem.l (sp)+,d1-d4 (44)
  1442.         rts             (16)
  1443.  
  1444.         page
  1445. *************************************************************************
  1446. *                                                                       *
  1447. *       Integer Square Root (32 to 16 bit).                             *
  1448. *                                                                       *
  1449. *       (Exact method, not approximate).                                *
  1450. *                                                                       *
  1451. *       Call with:                                                      *
  1452. *               D0.L = Unsigned number.                                 *
  1453. *                                                                       *
  1454. *       Returns:                                                        *
  1455. *               D0.L = SQRT(D0.L)                                       *
  1456. *                                                                       *
  1457. *       Uses:   D1-D4 as temporaries --                                 *
  1458. *               D1 = Error term;                                        *
  1459. *               D2 = Running estimate;                                  *
  1460. *               D3 = High bracket;                                      *
  1461. *               D4 = Loop counter.                                      *
  1462. *                                                                       *
  1463. *       Notes:  Result fits in D0.W, but is valid in longword.          *
  1464. *                                                                       *
  1465. *               Takes from 1080 to 1236 cycles (including rts.)         *
  1466. *                                                                       *
  1467. *               Two of the 16 passes are unrolled from the loop so that *
  1468. *               quicker instructions may be used where there is no      *
  1469. *               danger of overflow (in the early passes).               *
  1470. *                                                                       *
  1471. *               Instruction times for branch-type instructions          *
  1472. *               listed as (X/Y) are for (taken/not taken).              *
  1473. *                                                                       *
  1474. *************************************************************************
  1475.  
  1476. *                       Cycles
  1477. glsqrt  movem.l d1-d4,-(sp) (40)
  1478.         moveq #13,d4    (4)     ; Loop count (bits-1 of result).
  1479.         moveq #0,d1     (4)     ; Error term in D1.
  1480.         moveq #0,d2     (4)
  1481. lsqrt1  add.l d0,d0     (8)     ; Get 2 leading bits a time and add
  1482.         addx.w d1,d1    (4)     ; into Error term for interpolation.
  1483.         add.l d0,d0     (8)     ; (Classical method, easy in binary).
  1484.         addx.w d1,d1    (4)
  1485.         add.w d2,d2     (4)     ; Running estimate * 2.
  1486.         move.w d2,d3    (4)
  1487.         add.w d3,d3     (4)
  1488.         cmp.w d3,d1     (4)
  1489.         bls.s lsqrt2    (10/8)  ; New Error term > 2* Running estimate?
  1490.         addq.w #1,d2    (4)     ; Yes, we want a '1' bit then.
  1491.         addq.w #1,d3    (4)     ; Fix up new Error term.
  1492.         sub.w d3,d1     (4)
  1493. lsqrt2  dbra d4,lsqrt1  (10/14) ; Do first 14 bit-pairs.
  1494.  
  1495.         add.l d0,d0     (8)     ; Do 15-th bit-pair.
  1496.         addx.w d1,d1    (4)
  1497.         add.l d0,d0     (8)
  1498.         addx.l d1,d1    (8)
  1499.         add.w d2,d2     (4)
  1500.         move.l d2,d3    (4)
  1501.         add.w d3,d3     (4)
  1502.         cmp.l d3,d1     (6)
  1503.         bls.s lsqrt3    (10/8)
  1504.         addq.w #1,d2    (4)
  1505.         addq.w #1,d3    (4)
  1506.         sub.l d3,d1     (8)
  1507.  
  1508. lsqrt3  add.l d0,d0     (8)     ; Do 16-th bit-pair.
  1509.         addx.l d1,d1    (8)
  1510.         add.l d0,d0     (8)
  1511.         addx.l d1,d1    (8)
  1512.         add.w d2,d2     (4)
  1513.         move.l d2,d3    (4)
  1514.         add.l d3,d3     (8)
  1515.         cmp.l d3,d1     (6)
  1516.         bls.s lsqrt4    (10/8)
  1517.         addq.w #1,d2    (4)
  1518. lsqrt4  move.w d2,d0    (4)
  1519.         movem.l (sp)+,d1-d4 (44)
  1520.         rts             (16)
  1521.  
  1522.         end
  1523. -- 
  1524. +----------------+
  1525. ! II      CCCCCC !  Jim Cathey
  1526. ! II  SSSSCC     !  ISC-Bunker Ramo
  1527. ! II      CC     !  TAF-C8;  Spokane, WA  99220
  1528. ! IISSSS  CC     !  UUCP: uunet!isc-br!jimc (jimc@isc-br.isc-br.com)
  1529. ! II      CCCCCC !  (509) 927-5757
  1530.  
  1531. +++++++++++++++++++++++++++
  1532.  
  1533. >From lasley@umdsp.umd.edu (Scott E. Lasley)
  1534. Date: Wed,  4 May 1994 20:25:02 -0400
  1535. Organization: Space Physics Group, University of Maryland
  1536.  
  1537. In article <rmah-030594174155@rmah.dialup.access.net>, rmah@panix.com (Robert 
  1538. S. Mah) writes:
  1539. > There is an article on generating very fast square root aproximations 
  1540. > in the book "Graphics Gems", Ed. Glassner. 
  1541. >  
  1542. > It generates a lookup table which is indexed by munging the exponent 
  1543. > of the argument and then uses the mantissa to do an (linear?) 
  1544. > aproximation to the final result.  It's fairly accurate to within a 
  1545. > few decimal points.  I think the source code is also available 
  1546. > somewhere on the net, but I'm afraid I don't know where. 
  1547.  
  1548. some (perhaps all) of the code in the Graphics Gems series of books can be
  1549. found at ftp.princeton.edu.  here is a URL
  1550.  
  1551. ftp://ftp.princeton.edu//pub/Graphics/GraphicsGems
  1552.  
  1553. there are directories for books I through IV. the ReadMe file in the 
  1554. GemsIII directory contains the following line:
  1555.  
  1556.     sqrt.c        II.1    Steve Hill, "IEEE Fast Square Root"
  1557.  
  1558. hope this helps,
  1559.  
  1560.  
  1561. lasley@umdsp.umd.edu
  1562. "... and there were bumper stickers saying "Free Love"
  1563.  like it was some kind of political prisoner..."  David Wilcox
  1564.  
  1565.  
  1566. +++++++++++++++++++++++++++
  1567.  
  1568. >From nagle@netcom.com (John Nagle)
  1569. Date: Thu, 5 May 1994 02:23:34 GMT
  1570. Organization: NETCOM On-line Communication Services (408 241-9760 guest)
  1571.  
  1572. busfield@hurricane.seas.ucla.edu (John D. Busfield) writes:
  1573. >    Does anyone have an algorithm or code for computing square roots.
  1574. >The emphasis is on speed rather than accuracy in that I only need the
  1575. >result rounded to the nearest integer (ie sqrt(1000) = 31 or 32).
  1576. >Thanks in advance.
  1577.  
  1578.      The classic for floating point is to check the exponent and if odd,
  1579. shift the mantissa right one bit.  Then halve the exponent.  Use the
  1580. high 4 bits of the mantissa to select a starting mantissa from a table of
  1581. 16 values.  Then execute Newton's Method for two or three iterations,
  1582. written out in line.  On a machine with an FPU, this beats most iterative
  1583. methods.  Try it on a PPC.  This may actually be faster than an 
  1584. iterative integer method.
  1585.  
  1586.                     John Nagle
  1587.  
  1588. +++++++++++++++++++++++++++
  1589.  
  1590. >From Ron_Hunsinger@bmug.org (Ron Hunsinger)
  1591. Date: Thu,  5 May 94 05:35:48 PST
  1592. Organization: Berkeley Macintosh Users Group
  1593.  
  1594. parkb@bigbang.Stanford.EDU (Brian Park) writes:
  1595.  
  1596. >lsqrt2() - traditional Newton's method
  1597. >--------
  1598. >The traditional Newton's method of getting y = sqrt(n), coded as lsqrt2()
  1599. >below)
  1600. >
  1601. >n = y^2
  1602. >y(0) = n
  1603. >y(i+1) = (y(i) + n/y(i))/2
  1604. >
  1605. >is second-order convergent, 
  1606.  
  1607. You can do square root much faster than this.  Square root is about as
  1608. complex, and takes about as much time, as a divide.  A square root is
  1609. like a division in which the quotient and divisor are equal.
  1610. The usual division algorithm knows the divisor from the beginning, and
  1611. discovers the quotient a bit at a time.  You just have to tweak the
  1612. algorithm a little so that it discovers the divisor and quotient in
  1613. parallel, a bit at a time.
  1614.  
  1615. Think about how you would calculate square root by hand.  Then try
  1616. to do it in binary.  Notice how easy it becomes.
  1617.  
  1618. >My point is that Newton's method is O(log_2(n)) and you are not going
  1619. >to do much better than that.  
  1620.  
  1621. Newton's method is O(log n) ITERATIONS, but you do a divide in each 
  1622. iteration.  If division takes O(log n) shift-subtracts, then you have
  1623. a run time of O((log n)^2) shift-subtracts, compared to only O(log n)
  1624. shift-subtracts using a modified divide algorithm.
  1625.  
  1626. [Not that it really matters.  You aren't writing an arbitrary-precision
  1627. square root routine.  You have a fixed upper bound on the size of the
  1628. input, and ANY operation with only a finite number of valid inputs
  1629. can be implemented in O(1) time.]
  1630.  
  1631. [And if you have a very fast divide, as fast as a shift-subtract, as
  1632. might happen if you use a hardware divide instruction on a RISC computer,
  1633. then both methods might have nearly the same speed.  But if shifting
  1634. is faster than division, Newton's method is going to lose.]
  1635.  
  1636. -Ron Hunsinger
  1637.  
  1638. +++++++++++++++++++++++++++
  1639.  
  1640. >From afcjlloyd@aol.com (AFC JLloyd)
  1641. Date: 5 May 1994 12:37:02 -0400
  1642. Organization: America Online, Inc. (1-800-827-6364)
  1643.  
  1644. In article <2q91dp$rf@nntp2.Stanford.EDU>, parkb@bigbang.Stanford.EDU (Brian
  1645. Park) writes:
  1646.  
  1647. >>>
  1648. But let me empasize that even with straight Newton's method is O(log_2(n)),
  1649. Sqrt(10^9) takes only 19 iterations, as you can verify.  That's only 19
  1650. integer divisions.  How fast do you want your square root to be?
  1651. <<<
  1652.  
  1653. If you simply provide a better starting estimate you can reduce your 19
  1654. iterations
  1655. down to a maximum of 5.  A very cheap way to provide a better estimate is to
  1656. find the most significant bit and use it to estimate log2(N) and thus sqrt(N).
  1657. I don't know about you, but when I want fast code I'll take a factor of four
  1658. anyway I can get. 
  1659.  
  1660. However, if you're really out for speed, it turns out that Newton's
  1661. method is not the best.  Yesterday,  
  1662. pottier@corvette.ens.fr (Francois Pottier) posted an algorithm
  1663. by (Dr.) John Bruner,   bruner@csrd.uiuc.edu:
  1664.  
  1665. >>>>
  1666. unsigned int isqrt(unsigned long x)
  1667. {
  1668.  unsigned long r, nr, m;
  1669.  
  1670.  r = 0;
  1671.  m = 0x40000000;
  1672.  do {
  1673.   nr = r + m;
  1674.   if (nr <= x) {
  1675.    x -= nr;
  1676.    r = nr + m;
  1677.   }
  1678.   r >>= 1;
  1679.   m >>= 2;
  1680.  } while (m != 0);
  1681.  
  1682.  return(r);
  1683. }
  1684. <<<<
  1685.  
  1686. (I've removed two lines of code that round the result up if
  1687. rounding to nearest integer is desired).
  1688. This is an incredibly great algorithm, which uses exactly
  1689. 16 iterations but no integer multiply or divides.
  1690.  
  1691. However,  if you really want the fastest possible code, 
  1692. you should rewrite it like this:
  1693.  
  1694. unsigned short isqrt(register unsigned long x)
  1695. {
  1696.  register unsigned long r;
  1697.  register unsigned long nr;
  1698.  register unsigned long m;
  1699.  
  1700.  r = 0;
  1701.  m = 0x40000000;
  1702.   nr = m;       if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1703.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1704.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1705.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1706.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1707.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1708.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1709.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1710.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1711.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1712.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1713.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1714.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1715.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1716.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1; m >>= 2;
  1717.   nr = r + m; if (nr <= x) { x -= nr; r = nr + m; } r >>= 1;
  1718.  
  1719.   return(r);
  1720. }
  1721.  
  1722. This code is 40% faster (on my 840av) than code that I have been 
  1723. using that used 4 iterations of Newton-Raphson after seeding 
  1724. along the lines I mentioned above.
  1725.  
  1726. It may be possible to speed this up even further by using the
  1727. fast estimate of Log2(N) to reduce the number of iterations
  1728. from 16 to the absolute minimum (ceil(Log2(N)/2), though
  1729. I expect the improvement to be minimal since each iteration of
  1730. this algorithm is so cheap.
  1731.  
  1732. Jim Lloyd
  1733. afcjlloyd@aol.com
  1734.  
  1735.  
  1736. +++++++++++++++++++++++++++
  1737.  
  1738. >From trussler@panix.com (Tom Russler)
  1739. Date: Fri, 06 May 1994 00:38:31 -0400
  1740. Organization: PANIX Public Access Internet and UNIX (NYC)
  1741.  
  1742.  busfield@hurricane.seas.ucla.edu (John D. Busfield) writes:
  1743.  >    Does anyone have an algorithm or code for computing square roots.
  1744.  >The emphasis is on speed rather than accuracy in that I only need the
  1745.  >result rounded to the nearest integer (ie sqrt(1000) = 31 or 32).
  1746.  >Thanks in advance.
  1747.  
  1748. In 68000 assembly in THINK C:
  1749.  
  1750.              move.l     number, d0
  1751.              move.l     #1, d1
  1752.              move.l     d0, d2
  1753.       @1     cmp.l      d1, d2
  1754.              ble           @2
  1755.              lsl.l      #1, d1
  1756.              lsr.l      #1, d2
  1757.              bra           @1
  1758.       @2     add.l      d2, d1
  1759.              lsr.l   #1, d1
  1760.              divu       d1, d0
  1761.              add.w      d1, d0
  1762.              add.w      #1, d0
  1763.              lsr.w      #1, d0
  1764.  
  1765. -- 
  1766. Tom Russler
  1767. trussler@panix.com
  1768.  
  1769. +++++++++++++++++++++++++++
  1770.  
  1771. >From zstern@adobe.com (Zalman Stern)
  1772. Date: Fri, 6 May 1994 04:35:37 GMT
  1773. Organization: Adobe Systems Incorporated
  1774.  
  1775. Ron_Hunsinger@bmug.org (Ron Hunsinger) writes
  1776. > [And if you have a very fast divide, as fast as a shift-subtract, as
  1777. > might happen if you use a hardware divide instruction on a RISC computer,
  1778.  
  1779. This is not even close to true for any RISC implementation I know of. If the  
  1780. divisor is loop-invariant, one can multiply by the reciprocal which may be a  
  1781. single cycle operation, however this is not the case in the example being  
  1782. discussed. Most RISC architecture now include a floating-point square root  
  1783. instruction. This is partially due to this operations similarity to division  
  1784. (i.e. can use the same hardware) and partially due to its common appearance  
  1785. in electrical CAD codes :-)
  1786.  
  1787. I believe the integer square root routine I use is based on the algorithm  
  1788. Ron referred to. It has the following comment at the top (thanks to Mark  
  1789. Hamburg):
  1790.  
  1791. /*
  1792.  *      A square-root routine.  See Dijkstra, "A Discipline of Programming",
  1793.  *      page 65.
  1794.  */
  1795.  
  1796. I threw in an optimization to use the PowerPC count-leading-zeros  
  1797. instruction to efficiently reduce the number of iterations. (There is a  
  1798. similar instruction on the 68K.) The result is competitive with a lookup  
  1799. table based method for computing sqrt(x^2 + y^2) that uses a divide. (I'd  
  1800. post the code, but I didn't write it and I'm sure Adobe would frown on my  
  1801. doing so. Besides, reading Dijkstra is good for you :-))
  1802. --
  1803. Zalman Stern           zalman@adobe.com            (415) 962 3824
  1804. Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
  1805.           There is no lust like the present.
  1806.  
  1807. +++++++++++++++++++++++++++
  1808.  
  1809. >From hall_j@sat.mot.com (Joseph Hall)
  1810. Date: Thu, 5 May 1994 21:55:49 GMT
  1811. Organization: Motorola Inc., Satellite Communications
  1812.  
  1813. Seems it was nagle@netcom.com (John Nagle) who said:
  1814. >busfield@hurricane.seas.ucla.edu (John D. Busfield) writes:
  1815. >>    Does anyone have an algorithm or code for computing square roots.
  1816. >>The emphasis is on speed rather than accuracy in that I only need the
  1817. >>result rounded to the nearest integer (ie sqrt(1000) = 31 or 32).
  1818. >>Thanks in advance.
  1819. >
  1820. >     The classic for floating point is to check the exponent and if odd,
  1821. >shift the mantissa right one bit.  Then halve the exponent. [...]
  1822.  
  1823. You can consult Plaugher's "The Standard C Library" for a portable
  1824. floating point sqrt.  For a positive real number, the algorithm is:
  1825.  
  1826.   1) separate exponent and mantissa -- basically bit-masking except
  1827.        in cases of gradual underflow
  1828.   2) compute a quadratic least-squares fit to sqrt for the mantissa
  1829.        (y = (-.1984742*x+.8804894)*x + .3176687)
  1830.   3) follow with 3 iterations of Newton's method (y = .5*(y+x/y))
  1831.   4) if exponent is odd, a) multiply mantissa by sqrt(2) and
  1832.                          b) subtract 1 from exponent
  1833.   5) divide exponent by 2
  1834.   6) reassemble exponent and mantissa
  1835.  
  1836. Right-shifting the mantissa for odd exponents before computing
  1837. the root, to eliminate the multiplication by sqrt(2), is harder to 
  1838. express portably, but is certainly possible.  Plaugher doesn't make
  1839. any particular efforts to replace things like ".5 * x" with shifts.
  1840.  
  1841. Handy little book.  ISBN 0-13-131509-9.
  1842.  
  1843. (begin digression)
  1844.  
  1845. Plaugher uses conventional floating-point techniques to compute
  1846. transcendental functions.  This is pretty efficient, and these days
  1847. may be as good as any technique.  However, there are also algorithms
  1848. that allow you to compute trigonometric functions, as well as exponent
  1849. and log, by using only shifts and adds/subtracts--as if you were doing a
  1850. divide.  In fact, the computational effort is just twice that of
  1851. a divide.  I have seen relatively few references to these techniques,
  1852. but they are easy to implement.
  1853.  
  1854. For example, to compute an exponent, you need a table of ln(101(2)),
  1855. ln(11(2)), ln(1(2)), ln(1.1(2)), ln(1.01(2)), ln(1.001(2)), etc.   
  1856. Then you can code a fixed-point version like this (please excuse typos 
  1857. since I can't paste this directly in here at the moment):
  1858.  
  1859.   unsigned long logTbl[] = 
  1860.       { /* binary ln((2^i + 65536)/65536), for i == 32..1), e.g. */
  1861.         0xa65b1, 0x9b441, 0x902d3 ... 
  1862.         /* ln 2147549184/65536, ln 1073807360/65536, ln 536936448/65536 */ };
  1863.  
  1864.   unsigned long fexp(unsigned long x)
  1865.   {
  1866.     long i = 1L, j = 0L, k = 0x10000L, l = 0L, *lt = logTbl - 1;
  1867.     while (i <= 32) {
  1868.       j = l + lt[i];
  1869.       if (j > x) {
  1870.         i++;
  1871.       } else {
  1872.         l = j;
  1873.         k += k >> i;
  1874.       }
  1875.     }
  1876.     return k;
  1877.   }
  1878.  
  1879. This computes the exponent iteratively in k.  The log of the approximation
  1880. is maintained in l.  If l + the current entry in the table is <=
  1881. than the value you are computing the exponent of, then you add the
  1882. log in the table to l, and multiply k by a number that is conveniently
  1883. in the form 1 + some power of 2.  Repeat until the table is exhausted.
  1884.  
  1885. These days this may not be any faster than using the coprocessor.  However,
  1886. this technique was occasionally used to write very high-performance libraries 
  1887. for 8- and early 16-bit processors.  I doubt it was ever used in any
  1888. commercial BASIC, though, because it is not well known, and BASIC would
  1889. have been a hell of a lot faster for numerical work if it had been.  I first
  1890. heard this technique described in the mid 70s, but the literature goes
  1891. back to at least the 60s.
  1892.  
  1893. I wonder if this technique has ever been used to implement transcendental 
  1894. functions in microcode.  At one time I was thinking of trying to get it 
  1895. working on a TI bit slice CPU, that is, build my own coprocessor.  :-)
  1896.  
  1897. -- 
  1898. Joseph Nathan Hall | Joseph's Law of Interface Design: Never give your users
  1899. Software Architect | a choice between the easy way and the right way.
  1900. Gorca Systems Inc. |                 joseph@joebloe.maple-shade.nj.us (home)
  1901. (on assignment)    | (602) 732-2549 (work)  Joseph_Hall-SC052C@email.mot.com
  1902.  
  1903. +++++++++++++++++++++++++++
  1904.  
  1905. >From Ron_Hunsinger@bmug.org (Ron Hunsinger)
  1906. Date: Sat,  7 May 94 13:41:39 PST
  1907. Organization: Berkeley Macintosh Users Group
  1908.  
  1909. parkb@bigbang.Stanford.EDU (Brian Park) writes:
  1910.  
  1911. >But let me empasize that even with straight Newton's method is O(log_2(n)),
  1912. >Sqrt(10^9) takes only 19 iterations, as you can verify.  That's only 19
  1913. >integer divisions.  How fast do you want your square root to be?
  1914.  
  1915. I want it to be as fast as a single integer division.  Why take 19 times
  1916. as long as I have to?
  1917.  
  1918.  
  1919.  
  1920. zstern@adobe.com (Zalman Stern) writes:
  1921.  
  1922. >Ron_Hunsinger@bmug.org (Ron Hunsinger) writes
  1923. >> [And if you have a very fast divide, as fast as a shift-subtract, as
  1924. >> might happen if you use a hardware divide instruction on a RISC computer,
  1925. >
  1926. >This is not even close to true for any RISC implementation I know of. 
  1927.  
  1928. Glad to hear it.  I only included the comment because I did not have
  1929. instruction timings handy, and I was afraid someone was going to come 
  1930. along and say I needn't worry about avoiding divides because on the 
  1931. PowerPC (or some other RISC computer) EVERYTHING, including divide,
  1932. took only a single cycle, and so divide was just as fast as shift.
  1933.  
  1934. I knew shift couldn't be slower than divide, and if it really is faster
  1935. (which is reasonable), then finding a square root algorithm that does
  1936. not do any divides is a worthwhile objective.
  1937.  
  1938. >I believe the integer square root routine I use is based on the algorithm  
  1939. >Ron referred to. It has the following comment at the top (thanks to Mark  
  1940. >Hamburg):
  1941. >
  1942. >/*
  1943. > *      A square-root routine.  See Dijkstra, "A Discipline of Programming",
  1944. > *      page 65.
  1945. > */
  1946.  
  1947. A distinct possibility, since I read all the Dijkstra books I could get
  1948. my hands on, way back when.  However, I knew that square root could be
  1949. done as quickly as division at least as far back as high school, before
  1950. I had ever heard of Dijkstra (or seen a computer for that matter).  As 
  1951. I said, the method suggests itself as soon as you assail to calculate 
  1952. square root using the traditional pencil and paper method in binary.
  1953.  
  1954. >I threw in an optimization to use the PowerPC count-leading-zeros  
  1955. >instruction to efficiently reduce the number of iterations. (There is a  
  1956. >similar instruction on the 68K.) 
  1957.  
  1958. There is?  Is this a 68040 instruction?  I can't find any such instruction
  1959. at least through the 68030.  I thought the 68040 was just a 68030 with
  1960. a bigger cache and a built-in FPU.  Sure would be nice, though.  The
  1961. Unisys A-series computers have a similar instruction, accessible through
  1962. the built-in FIRSTONE function in Burroughs Extended Algol, which I
  1963. found many interesting (and not always obvious) uses for.
  1964.  
  1965. >The result is competitive with a lookup  
  1966. >table based method for computing sqrt(x^2 + y^2) that uses a divide. (I'd  
  1967. >post the code, but I didn't write it and I'm sure Adobe would frown on my  
  1968. >doing so. Besides, reading Dijkstra is good for you :-))
  1969.  
  1970. No problem.  I'll post mine, which I wrote from scratch before checking
  1971. your Dijkstra reference. My routine and his, neither of which uses divides
  1972. (except by 2 or 4), bear only a vague similarity.  (But reading Dijkstra 
  1973. is still good for you.)  The whole thing is as fast as a single divide 
  1974. done by subroutine (as, for example, would be required to divide 32-bit 
  1975. integers on a 68000).
  1976.  
  1977. Normally, a division subroutine will keep the divisor fixed and shift
  1978. the dividend past it, doing subtractions (and incrementing the quotient)
  1979. as needed.  My first thought was to do the same thing, but that's messy
  1980. to do in C.  (In assembler, you would use LSL, ROXL to shift bits out
  1981. of one register into another; but that doesn't map well to C.)  So 
  1982. instead, I keep the dividend fixed, and shift the divisor right.  Just as
  1983. in the pencil and paper square root method, you take the digits (bits) of
  1984. the argument two at a time.  But since the quotient (a.k.a. the square
  1985. root) is accumulating bits one at a time in the opposite direction, it
  1986. ends up only shifting one bit at a time.  
  1987.  
  1988. Without further comment, my version (which is meant to be fast, not 
  1989. necessarily readable) follows:
  1990.  
  1991. #define BITS 32
  1992. // BITS is the smallest even integer such that 2^BITS > ULONG_MAX.
  1993. // If you port this routine to a computer where 2^(BITS-1) > ULONG_MAX
  1994. // (Unisys A-series, for example, where integers would generally be
  1995. // stored in the 39-bit mantissa of a 48-bit word), unwind the first 
  1996. // iteration of the loop, and special-case references to 'half' in that 
  1997. // first iteration so as to avoid overflow.
  1998.  
  1999. unsigned long lsqrt (unsigned long n) {
  2000.     // Compute the integer square root of the integer argument n
  2001.     // Method is to divide n by x computing the quotient x and remainder r
  2002.     // Notice that the divisor x is changing as the quotient x changes
  2003.  
  2004.     // Instead of shifting the dividend/remainder left, we shift the
  2005.     // quotient/divisor right.  The binary point starts at the extreme
  2006.     // left, and shifts two bits at a time to the extreme right.
  2007.  
  2008.     // The residue contains n-x^2.  (Within these comments, the ^ operator
  2009.     // signifies exponentiation rather than exclusive or.  Also, the /
  2010.     // operator returns fractions, rather than truncating, so 1/4 means
  2011.     // one fourth, not zero.)
  2012.  
  2013.     // Since (x + 1/2)^2 == x^2 + x + 1/4,
  2014.     //   n - (x + 1/2)^2 == (n - x^2) - (x + 1/4)
  2015.     // Thus, we can increase x by 1/2 if we decrease (n-x^2) by (x+1/4)
  2016.  
  2017.     unsigned long residue;   // n - x^2
  2018.     unsigned long root;      // x + 1/4
  2019.     unsigned long half;      // 1/2
  2020.  
  2021.     residue = n;             // n - (x = 0)^2, with suitable alignment
  2022.     root = 1 << (BITS - 2);  // x + 1/4, shifted left BITS places
  2023.     half = root + root;      // 1/2, shifted left BITS places
  2024.     
  2025.     do {
  2026.         if (root <= residue) {   // Whenever we can,
  2027.             residue -= root;         // decrease (n-x^2) by (x+1/4)
  2028.             root += half; }          // increase x by 1/2
  2029.         half >>= 2;          // Shift binary point 2 places right
  2030.         root -= half;        // x{+1/2}+1/4 - 1/8 == x{+1/2}+1/8
  2031.         root >>= 1;          // 2x{+1}+1/4, shifted right 2 places
  2032.         } while (half);      // When 1/2 == 0, binary point is at far right
  2033.     
  2034.     // Omit the following line to truncate instead of rounding
  2035.     if (root < residue) ++root;
  2036.     
  2037.     return root;   // Guaranteed to be correctly rounded (or truncated)
  2038.     }
  2039.  
  2040. Enjoy,
  2041. -Ron Hunsinger
  2042.  
  2043. +++++++++++++++++++++++++++
  2044.  
  2045. >From Ron_Hunsinger@bmug.org (Ron Hunsinger)
  2046. Date: Sun,  8 May 94 04:45:40 PST
  2047. Organization: Berkeley Macintosh Users Group
  2048.  
  2049. trussler@panix.com (Tom Russler) writes:
  2050. >
  2051. > busfield@hurricane.seas.ucla.edu (John D. Busfield) writes:
  2052. > >    Does anyone have an algorithm or code for computing square roots.
  2053. > >The emphasis is on speed rather than accuracy in that I only need the
  2054. > >result rounded to the nearest integer (ie sqrt(1000) = 31 or 32).
  2055. > >Thanks in advance.
  2056. >
  2057. >In 68000 assembly in THINK C:
  2058. >
  2059. >     move.l number, d0
  2060. >     move.l #1, d1
  2061. >     move.l d0, d2
  2062. >  @1 cmp.l  d1, d2
  2063. >     ble   @2
  2064. >     lsl.l  #1, d1
  2065. >     lsr.l  #1, d2
  2066. >     bra   @1
  2067. >  @2 add.l  d2, d1
  2068. >     lsr.l   #1, d1
  2069. >     divu   d1, d0
  2070. >     add.w  d1, d0
  2071. >     add.w  #1, d0
  2072. >     lsr.w  #1, d0
  2073.  
  2074. Sorry.  Valiant effort, but no cigar.  You don't handle boundary 
  2075. conditions correctly.  Examine what happens when 'number' is 0xFFFFaaaa, 
  2076. where aaaa is any arbitrary bit pattern.
  2077.  
  2078. >     move.l number, d0     ; d0 = 0xFFFFaaaa
  2079. >     move.l #1, d1         ; d1 = 0x00000001
  2080. >     move.l d0, d2         ; d2 = 0xFFFFaaaa
  2081.  
  2082. >  @1 cmp.l  d1, d2
  2083. >     ble   @2
  2084. >     lsl.l  #1, d1
  2085. >     lsr.l  #1, d2
  2086. >     bra   @1
  2087.  
  2088.        ; after 16 iterations, you break out of the above loop, with:
  2089.                                ; d1 = 0x00010000 = 65536
  2090.                                ; d2 = 0x0000FFFF = 65535
  2091.  
  2092. >  @2 add.l  d2, d1         ; d1 = 0x0001FFFF
  2093. >     lsr.l   #1, d1         ; d1 = 0x0000FFFF = 65535
  2094. >     divu   d1, d0   <-----OVERFLOW:  d0/d1 >= 65536, to big for a short
  2095.  
  2096. In fact, you should have seen that overflow was a problem.  DIVU will
  2097. always overflow, no matter what the divisor, if the dividend is greater
  2098. than 65535*65535 = 0xFFFE0001.
  2099.  
  2100. You may have been counting on the fact that, if overflow is detected,
  2101. the operands are unaffected, but that doesn't help.  The contents of 
  2102. d0.w after the divide is aaaa, which was a completely arbitrary value.
  2103. Continuing:
  2104.  
  2105. >     add.w  d1, d0   <-----OVERFLOW AGAIN:  Since d1=65535, the
  2106. >     add.w  #1, d0         ; effect of these two instruction is to
  2107.                                ; overflow at some point, but otherwise
  2108.                                ; do nothing.  d0 still contains aaaa
  2109.  
  2110. >     lsr.w  #1, d0         ; divide the garbage by 2.
  2111.  
  2112. The final result is in the range 0..32767.  The correct result should
  2113. be 65535 (if aaaa is 0000) or 65536 (for any other value of aaaa).
  2114. Again, you should have seen this coming.  Your final instruction can
  2115. never return a value >32767, meaning that you cannot possibly return
  2116. the correct result for any number > 32767*32768 = 0x3FFF8000.
  2117.  
  2118.  
  2119. You also do not achieve the stated accuracy goal, "I [only] need the
  2120. result rounded to the nearest integer", even when you don't overflow.
  2121.  
  2122. Suppose 'number' = 0x10004000 = 268451840.  Your code computes a value
  2123. of 16794.  The correctly rounded value is 16384.  Off by 410 is not "the
  2124. nearest integer".
  2125.  
  2126. -Ron "who gets very picky sometimes :)" Hunsinger
  2127.  
  2128. +++++++++++++++++++++++++++
  2129.  
  2130. >From fixer@faxcsl.dcrt.nih.gov (Chris Gonna' Find Ray Charles Tate)
  2131. Date: Mon, 9 May 1994 14:04:10 GMT
  2132. Organization: DCRT, NIH, Bethesda, MD
  2133.  
  2134. In article <0014A722.fc@bmug.org>, Ron_Hunsinger@bmug.org (Ron Hunsinger) writes:
  2135. >
  2136. >zstern@adobe.com (Zalman Stern) writes:
  2137. >>
  2138. >>I threw in an optimization to use the PowerPC count-leading-zeros  
  2139. >>instruction to efficiently reduce the number of iterations. (There is a  
  2140. >>similar instruction on the 68K.) 
  2141. >
  2142. >There is?  Is this a 68040 instruction?  I can't find any such instruction
  2143. >at least through the 68030.  I thought the 68040 was just a 68030 with
  2144. >a bigger cache and a built-in FPU.
  2145.  
  2146. I think you're looking for the BFFFO instruction, which my 680x0 family
  2147. reference describes as "Find First One in Bit Field," and says it's
  2148. a 60820 instruction (and later, of course).
  2149.  
  2150. The book I'm looking in is Motorola's "M68000 Family Programmer's
  2151. Reference Manual," which doesn't seem to have any Library of Congress
  2152. registration (!), but which is Motorola part number M68000PM/AD.
  2153.  
  2154. - -------------------------------------------------------------
  2155. Christopher Tate             |  "So he dropped the heart - 
  2156. MSD, Inc.                    |     the floor's clean."
  2157. fixer@faxcsl.dcrt.nih.gov    |                 - Sidney Harris
  2158.  
  2159. +++++++++++++++++++++++++++
  2160.  
  2161. >From christer@cs.umu.se (Christer Ericson)
  2162. Date: Tue, 10 May 1994 10:24:38 GMT
  2163. Organization: Dept. of Computing Science, Umea Univ., 901 87 Umea, Sweden
  2164.  
  2165. In <00148DC5.fc@bmug.org> Ron_Hunsinger@bmug.org (Ron Hunsinger) writes:
  2166. >
  2167. >parkb@bigbang.Stanford.EDU (Brian Park) writes:
  2168. >>[...suggests using Newton's method...]
  2169. >
  2170. >You can do square root much faster than this.
  2171.  
  2172. I beg to differ. In article <CpA23t.DwM@cs.umu.se> I posted an 68000-
  2173. based implementation of Newton's method (with quirks) which is something
  2174. like 20-30% faster than the equivalent hand-coded optimized assembly
  2175. version of the routine you posted in another article. It all depends on
  2176. how good your initial guess for Newton's method is.
  2177.  
  2178. So there! :-)
  2179.  
  2180.  
  2181. Christer Ericson --- Internet: christer@cs.umu.se --- tel: +46-90-166794
  2182. Department of Computer Science, University of Umea, S-90187 UMEA, SWEDEN
  2183.  
  2184. +++++++++++++++++++++++++++
  2185.  
  2186. >From afcjlloyd@aol.com (AFC JLloyd)
  2187. Date: 10 May 1994 18:01:03 -0400
  2188. Organization: America Online, Inc. (1-800-827-6364)
  2189.  
  2190. In article <CpL0x4.HKJ@cs.umu.se>, christer@cs.umu.se (Christer Ericson)
  2191. writes:
  2192.  
  2193. >In <00148DC5.fc@bmug.org> Ron_Hunsinger@bmug.org (Ron Hunsinger) writes:
  2194. >>
  2195. >>parkb@bigbang.Stanford.EDU (Brian Park) writes:
  2196. >>>[...suggests using Newton's method...]
  2197. >>
  2198. >>You can do square root much faster than this.
  2199. >
  2200. >I beg to differ. In article <CpA23t.DwM@cs.umu.se> I posted an 68000-
  2201. >based implementation of Newton's method (with quirks) which is something
  2202. >like 20-30% faster than the equivalent hand-coded optimized assembly
  2203. >version of the routine you posted in another article. It all depends on
  2204. >how good your initial guess for Newton's method is.
  2205.  
  2206. I agree with Christer.  Until this thread I had been using Newton's method
  2207. with 5 iterations for obtaining the square root of unsigned longs, where
  2208. the initial estimate came from finding the most signficant bit, using
  2209. that to estimate Log2(n), and using that to estimate sqrt(n).
  2210.  
  2211. When I saw this thread I tried the code attributed to Dr. John Bruner
  2212. (similar to Ron's code) and saw a 40% speedup over my Newton's method
  2213. code.  Convinced that this was a precious find,  I then tried to apply 
  2214. the same technique to taking the square root of Fixed point values and 
  2215. discovered that it couldn't beat my Newton's method code.  The reason 
  2216. was primarily that 24 (instead of 16) iterations are required for 
  2217. fixed point square root (the Fract case would require 31 iterations).
  2218.  
  2219. This caused me to do more thinking about Newton's method.  
  2220. The great thing about Newton's method is that it _doubles_ the 
  2221. precision with each iteration.  Of course, double of nothing
  2222. is nothing, so Newton's method is worthless if you give it a poor
  2223. estimate, but given a good estimate Newton's method is fantastic.
  2224.  
  2225. So, I decided to use a table lookup to provide the initial estimate for
  2226. Newton's method.  I found that I could reduce the number of iterations
  2227. down from five to _one_ for the integer case, and just _two_ iterations
  2228. for both the Fixed and Fract cases.  The resulting code is significantly
  2229. faster than any of my previous attempts.
  2230.  
  2231. Jim Lloyd
  2232. afcjlloyd@aol.com
  2233.  
  2234.  
  2235. +++++++++++++++++++++++++++
  2236.  
  2237. >From Ron_Hunsinger@bmug.org (Ron Hunsinger)
  2238. Date: Sat, 14 May 94 03:01:56 PST
  2239. Organization: Berkeley Macintosh Users Group
  2240.  
  2241. christer@cs.umu.se (Christer Ericson) writes:
  2242.  
  2243. >In <00148DC5.fc@bmug.org> Ron_Hunsinger@bmug.org (Ron Hunsinger) writes:
  2244. >>
  2245. >>parkb@bigbang.Stanford.EDU (Brian Park) writes:
  2246. >>>[...suggests using Newton's method...]
  2247. >>
  2248. >>You can do square root much faster than this.
  2249. >
  2250. >I beg to differ. In article <CpA23t.DwM@cs.umu.se> I posted an 68000-
  2251. >based implementation of Newton's method (with quirks) which is something
  2252. >like 20-30% faster than the equivalent hand-coded optimized assembly
  2253. >version of the routine you posted in another article. It all depends on
  2254. >how good your initial guess for Newton's method is.
  2255.  
  2256. You've got me mixed up with somebody else.  I did say you can do square
  2257. root much faster, and explained how, but I didn't post any assembly
  2258. version.  I posted the C version (which therefore has the advantage
  2259. that it can be compiled native for PowerPC, or ported easily to another
  2260. machine that doesn't even have to be binary, although of course it is
  2261. unlikely that shifting will be fast on a non-binary machine).
  2262.  
  2263. I saw two assembly versions.  One, which was quite long, very tightly
  2264. optimized, and attributed to Motorola, was indeed faster than my short 
  2265. simple C version, but not by all that much.  Also, it always truncated,
  2266. where mine would produce the correctly rounded result (or the truncated
  2267. result by commenting out one line if that's really what you wanted).
  2268.  
  2269. The other, very short assembler version was hopelessly flawed.  It
  2270. computed an initial guess that could be off by a factor of two, and
  2271. then did *ONE* iteration of Newton's method, and stopped there, producing
  2272. a value that was not even close (in absolute terms), even when it did
  2273. not lose all significance due to overflow.  If asked to take the square 
  2274. root of zero, it would divide by zero.  It probably was fast (when it
  2275. didn't crash), but who cares how quickly you get the wrong answer?
  2276.  
  2277. Which version was yours?
  2278.  
  2279. I'll be charitable and assume it was the Motorola version.  I no longer
  2280. have the original message, but I seem to recall the max running time
  2281. was something like 1262 cycles on a 68000, and (quite a bit) faster
  2282. on small values.  I modified my C version to special-case small values
  2283. too, and unwind the iterations of the main loop up to the iteration that
  2284. finds the high bit of the root.  The main benefit of special-casing small 
  2285. values is so I don't have to worry about that boundary in the remaining 
  2286. code -- I am then guaranteed that the (unrounded) root is at least two 
  2287. bits long.  And although I am not displeased by the improved efficiency, 
  2288. my main reason for unwinding the first iterations was to remove the 
  2289. restriction in the prior version that it would only work on machines in 
  2290. which the number of bits in an unsigned long was even.  This code will 
  2291. now work even on machines with odd integer sizes.  (Yes, Virginia, such 
  2292. machines do exist!  An example is the Unisys A-series computers, in which 
  2293. ALL arithmetic is done in floating point, and integers are just the special 
  2294. case where the exponent is zero and the integer value is stored in the 
  2295. 39-bit mantissa of a 48-bit word.)  
  2296.  
  2297. My improved C version appears at the end of this message.
  2298.  
  2299. I compiled it with MPW C with no special optimizations, tested it
  2300. thoroughly, and then disassembled the code and calculated the running
  2301. time on a 68000.  (On later machines, the presence of the cache makes
  2302. accurate timings much more difficult to do by hand.)  I did not make
  2303. any attempt to "improve" the C-generated code, although there are some 
  2304. easy and obvious optimizations available.  The running time for my
  2305. version (the one that correctly rounds), counting the RTS and the
  2306. (quite unnecessary) LINK/MOVEM.L/.../MOVE.L <rslt>,D0/MOVEM.L/UNLK is:
  2307.  
  2308.    If N <= 12 then 204+4N, else 620+46u+32z+6r, where
  2309.         N = input argument
  2310.         u = Number of one-bits in the unrounded root
  2311.         z = Number of non-leading zero-bits in the unrounded root
  2312.         r = 1 if rounding increases the root, else 0
  2313.  
  2314.    The actual running time for various values of N is:
  2315.  
  2316.                  N   Time  Comments
  2317.          ---------  -----  -------------------------
  2318.                  0    204  Best time
  2319.                 13    718  Best time not using lookup table
  2320.                625    822  This is a cut-point for the Motorola code
  2321.           0..65535    935  Average* time over inputs that fit in 16 bits
  2322.              65535    994  Worst time if N fits in 16 bits
  2323.      0..0xFFFFFFFF   1247  Average* time over all 32-bit inputs
  2324.         0xFFFFFFFF   1362  Worst case
  2325.        *average times computed assuming uniform distrubution of outputs
  2326.  
  2327. If my memory serves me right, this is only about 8% slower than the
  2328. hand-crafted Motorola code, which I think is a cheap price to pay for
  2329. the portability.  Especially considering that most of that difference 
  2330. is due to the fact that they split the general loop into a main loop 
  2331. that could get away with word-size operations for some variables, and 
  2332. a few unwound iterations that had to use long-sized operands.  Notice
  2333. that this is counterproductive on 68020 and up, where long operations 
  2334. are just as fast as word operations when the operands are in registers,
  2335. and the only effect of unwinding the last two iterations is to 
  2336. guarantee that they won't be in the cache.  
  2337.  
  2338. The compiled 68K code fits in 104 bytes (decimal). (96 bytes without
  2339. the debugger symbol. This really was a vanilla compile.)  How big was 
  2340. your code?  How big is the code cache on your machine?  How much of
  2341. your caller's code do you push out of the cache?
  2342.  
  2343.  
  2344. >So there! :-)
  2345.  
  2346. Same to you!!  :-)
  2347.  
  2348.  
  2349. #define lsqrt_max4pow (1UL << 30)
  2350. // lsqrt_max4pow is the (machine-specific) largest power of 4 that can
  2351. // be represented in an unsigned long.
  2352.  
  2353. unsigned long lsqrt (unsigned long n) {
  2354.     // Compute the integer square root of the integer argument n
  2355.     // Method is to divide n by x computing the quotient x and remainder r
  2356.     // Notice that the divisor x is changing as the quotient x changes
  2357.  
  2358.     // Instead of shifting the dividend/remainder left, we shift the
  2359.     // quotient/divisor right.  The binary point starts at the extreme
  2360.     // left, and shifts two bits at a time to the extreme right.
  2361.  
  2362.     // The residue contains n-x^2.  (Within these comments, the ^ operator
  2363.     // signifies exponentiation rather than exclusive or.  Also, the /
  2364.     // operator returns fractions, rather than truncating, so 1/4 means
  2365.     // one fourth, not zero.)
  2366.  
  2367.     // Since (x + 1/2)^2 == x^2 + x + 1/4,
  2368.     //   n - (x + 1/2)^2 == (n - x^2) - (x + 1/4)
  2369.     // Thus, we can increase x by 1/2 if we decrease (n-x^2) by (x+1/4)
  2370.  
  2371.     unsigned long residue;      // n - x^2
  2372.     unsigned long root;         // x + 1/4
  2373.     unsigned long half;         // 1/2
  2374.  
  2375.     residue = n;                // n - (x = 0)^2, with suitable alignment
  2376.     
  2377.     // if the correct answer fits in two bits, pull it out of a magic hat
  2378. #ifndef lsqrt_truncate
  2379.     if (residue <= 12)
  2380.         return (0x03FFEA94 >> (residue *= 2)) & 3;
  2381. #else
  2382.     if (residue <= 15)
  2383.         return (0xFFFEAA54 >> (residue *= 2)) & 3;
  2384. #endif
  2385.     root = lsqrt_max4pow;       // x + 1/4, shifted all the way left
  2386. //  half = root + root;         // 1/2, shifted likewise
  2387.     
  2388.     // Unwind iterations corresponding to leading zero bits 
  2389.     while (root > residue) root >>= 2;
  2390.     
  2391.     // Unwind the iteration corresponding to the first one bit
  2392.     // Operations have been rearranged and combined for efficiency
  2393.     // Initialization of half is folded into this iteration
  2394.     residue -= root;            // Decrease (n-x^2) by (0+1/4)
  2395.     half = root >> 2;           // 1/4, with binary point shifted right 2
  2396.     root += half;               // x=1.  (root is now (x=1)+1/4.)
  2397.     half += half;               // 1/2, properly aligned
  2398.  
  2399.     // Normal loop (there is at least one iteration remaining)
  2400.     do {
  2401.         if (root <= residue) {  // Whenever we can,
  2402.             residue -= root;        // decrease (n-x^2) by (x+1/4)
  2403.             root += half; }         // increase x by 1/2
  2404.         half >>= 2;             // Shift binary point 2 places right
  2405.         root -= half;           // x{+1/2}+1/4 - 1/8 == x{+1/2}+1/8
  2406.         root >>= 1;             // 2x{+1}+1/4, shifted right 2 places
  2407.         } while (half);         // When 1/2 == 0, bin. point is at far right
  2408.  
  2409. #ifndef lsqrt_truncate
  2410.     if (root < residue) ++root;  // round up if (x+1/2)^2 < n
  2411. #endif
  2412.     
  2413.     return root;        // Guaranteed to be correctly rounded (or truncated)
  2414.     }
  2415.  
  2416. -Ron Hunsinger
  2417.  
  2418. +++++++++++++++++++++++++++
  2419.  
  2420. >From christer@cs.umu.se (Christer Ericson)
  2421. Date: Mon, 16 May 1994 08:44:47 GMT
  2422. Organization: Dept. of Computing Science, Umea Univ., 901 87 Umea, Sweden
  2423.  
  2424. In <0014E819.fc@bmug.org> Ron_Hunsinger@bmug.org (Ron Hunsinger) writes:
  2425. >
  2426. >christer@cs.umu.se (Christer Ericson) writes:
  2427. >>[...]
  2428. >>I beg to differ. In article <CpA23t.DwM@cs.umu.se> I posted an 68000-
  2429. >>based implementation of Newton's method (with quirks) which is something
  2430. >>like 20-30% faster than the equivalent hand-coded optimized assembly
  2431. >>version of the routine you posted in another article. It all depends on
  2432. >>how good your initial guess for Newton's method is.
  2433. >
  2434. >You've got me mixed up with somebody else.  I did say you can do square
  2435. >root much faster, and explained how, but I didn't post any assembly
  2436. >version.  I posted the C version (which therefore has the advantage
  2437. >that it can be compiled native for PowerPC, or ported easily to another
  2438. >machine that doesn't even have to be binary, although of course it is
  2439. >unlikely that shifting will be fast on a non-binary machine).
  2440.  
  2441. Gosh! What if you read what I wrote above. I didn't claim your code was
  2442. written in assembly. I refer rather clearly to highly optimized assembly
  2443. code _equivalent_ to the C code you posted.
  2444.  
  2445.  
  2446. >I saw two assembly versions.  One, which was quite long, very tightly
  2447. >optimized, and attributed to Motorola, was indeed faster than my short 
  2448. >simple C version, but not by all that much.  Also, it always truncated,
  2449. >where mine would produce the correctly rounded result (or the truncated
  2450. >result by commenting out one line if that's really what you wanted).
  2451. >
  2452. >The other, very short assembler version was hopelessly flawed.  It
  2453. >computed an initial guess that could be off by a factor of two, and
  2454. >then did *ONE* iteration of Newton's method, and stopped there, producing
  2455. >a value that was not even close (in absolute terms), even when it did
  2456. >not lose all significance due to overflow.  If asked to take the square 
  2457. >root of zero, it would divide by zero.  It probably was fast (when it
  2458. >didn't crash), but who cares how quickly you get the wrong answer?
  2459. >
  2460. >Which version was yours?
  2461.  
  2462. Neither of these. Instead of arguing about some program you thought I
  2463. wrote, wouldn't it have been better (as well as making you look better)
  2464. if you had looked my article up, or in the case it had expired at your
  2465. site, requested a copy from me before making yourself silly in public?
  2466.  
  2467. Instead of commenting on your rather irrelevant comments on some code
  2468. that wasn't mine, I've appended below a copy of my code and if you
  2469. care to compare it to your code, I'll take the time to respond to
  2470. any comments you might have (size, speed, what have you). Fair?
  2471.  
  2472. Finally, the point I wanted to make was that an optimized version of
  2473. Newton's method very well beats an optimized version of the type of
  2474. algorithm your program is a version of. I'm not interested in any
  2475. "...b-b-b-but C is more portable..." arguments.
  2476.  
  2477.  
  2478. - - cut here ---
  2479. unsigned short ce_quick_sqrt(n)
  2480. register unsigned long n;
  2481. {
  2482.     asm {
  2483. ;-------------------------
  2484. ;
  2485. ; Routine       : ISQRT; integer square root
  2486. ; I/O parameters: d0.w = sqrt(d0.l)
  2487. ; Registers used: d0-d2/a0
  2488. ;
  2489. ; This is a highly optimized integer square root routine, based
  2490. ; on the iterative Newton/Babylonian method
  2491. ;
  2492. ;    r(n + 1) = (r(n) + A / R(n)) / 2
  2493. ;
  2494. ; Verified over the full interval [0x0L,0xFFFFFFFFL]
  2495. ;
  2496. ; Some minor compromises have been made to make it perform well
  2497. ; on the 68000 as well as 68020/030/040. This routine outperforms
  2498. ; the best of all other algorithms I've seen (except for a table
  2499. ; lookup).
  2500. ;
  2501. ; Copyright (c) Christer Ericson, 1993. All rights reserved.
  2502. ;
  2503. ; Christer Ericson, Dept. of Computer Science, University of Umea,
  2504. ; S-90187 UMEA, SWEDEN. Internet: christer@cs.umu.se
  2505. ;
  2506.  
  2507. ;-------------------------
  2508. ;
  2509. ; Macintosh preamble since THINK C passes first register param
  2510. ; in d7. Remove this section on any other machine
  2511. ;
  2512.     move.l    d7,d0
  2513. ;-------------------------
  2514. ;
  2515. ; Actual integer square root routine starts here
  2516. ;
  2517.     move.l    d0,a0        ; save original input value for the iteration
  2518.     beq.s    @exit        ; unfortunately we must special case zero
  2519.     moveq    #2,d1        ; init square root guess
  2520. ;-------------------------
  2521. ;
  2522. ; Speed up the process of finding a power of two approximation
  2523. ; to the actual square root by shifting an appropriate amount
  2524. ; when the input value is large enough
  2525. ;
  2526. ; If input values are word only, this section can be removed
  2527. ;
  2528.     move.l    d0,d2
  2529.     swap    d2        ; do [and.l 0xFFFF0000,d2] this way to...
  2530.     tst.w    d2        ; go faster on 68000 and to avoid having to...
  2531.     beq.s    @skip8        ; reload d2 for the next test below
  2532.     move.w    #0x200,d1    ; faster than lsl.w #8,d1 (68000)
  2533.     lsr.l    #8,d0
  2534. @skip8    and.w    #0xFE00,d2    ; this value and shift by 5 are magic
  2535.     beq.s    @skip4
  2536.     lsl.w    #5,d1
  2537.     lsr.l    #5,d0
  2538. @skip4
  2539.  
  2540. ;-------------------------
  2541. ;
  2542. ; This finds the power of two approximation to the actual square root
  2543. ; by doing the integer equivalent to sqrt(x) = 2 ^ (log2(x) / 2). This
  2544. ; is done by shifting the input value down while shifting the root
  2545. ; approximation value up until they meet in the middle. Better precision
  2546. ; (in the step described below) is gained by starting the approximation
  2547. ; at 2 instead of 1 (this means that the approximation will be a power
  2548. ; of two too large so remember to shift it down).
  2549. ;
  2550. ; Finally (and here's the clever thing) since, by previously shifting the
  2551. ; input value down, it has actually been divided by the root approximation
  2552. ; value already so the first iteration is "for free". Not bad, eh?
  2553. ;
  2554. @loop    add.l    d1,d1
  2555.     lsr.l    #1,d0
  2556.     cmp.l    d0,d1
  2557.     bcs.s    @loop
  2558. @skip    lsr.l    #1,d1        ; adjust the approximation
  2559.     add.l    d0,d1        ; here we just add and shift to...
  2560.     lsr.l    #1,d1        ; get the first iteration "for free"!
  2561. ;-------------------------
  2562. ;
  2563. ; The iterative root value is guaranteed to be larger than (or equal to)
  2564. ; the actual square root, except for the initial guess. But since the first
  2565. ; iteration was done above, the loop test can be simplified below
  2566. ; (Oh, without the bvs.s the routine will fail on most large numbers, like
  2567. ; for instance, 0xFFFF0000. Could there be a better way of handling these,
  2568. ; so the bvs.s can be removed? Nah...)
  2569. ;
  2570. @loop2    move.l    a0,d2        ; get original input value
  2571.     move.w    d1,d0        ; save current guess
  2572.     divu.w    d1,d2        ; do the Newton method thing
  2573.     bvs.s    @exit        ; if div overflows, exit with current guess
  2574.     add.w    d2,d1
  2575.     roxr.w    #1,d1        ; roxr ensures shifting back carry overflow
  2576.     cmp.w    d0,d1
  2577.     bcs.s    @loop2        ; exit with result in d0.w
  2578. @exit
  2579.     }
  2580. }
  2581.  
  2582. Christer Ericson --- Internet: christer@cs.umu.se --- tel: +46-90-166794
  2583. Department of Computer Science, University of Umea, S-90187 UMEA, SWEDEN
  2584.  
  2585. +++++++++++++++++++++++++++
  2586.  
  2587. >From Ron_Hunsinger@bmug.org (Ron Hunsinger)
  2588. Date: Tue, 24 May 94 23:23:06 PST
  2589. Organization: Berkeley Macintosh Users Group
  2590.  
  2591. christer@cs.umu.se (Christer Ericson) writes:
  2592.  
  2593. >In <0014E819.fc@bmug.org> Ron_Hunsinger@bmug.org (Ron Hunsinger) writes:
  2594. >>
  2595. >>christer@cs.umu.se (Christer Ericson) writes:
  2596. >>>[...]
  2597. >>>I beg to differ. In article <CpA23t.DwM@cs.umu.se> I posted an 68000-
  2598. >>>based implementation of Newton's method (with quirks) which is something
  2599. >>>like 20-30% faster than the equivalent hand-coded optimized assembly
  2600. >>>version of the routine you posted in another article. It all depends on
  2601. >>>how good your initial guess for Newton's method is.
  2602. >>
  2603. >>You've got me mixed up with somebody else.  I did say you can do square
  2604. >>root much faster, and explained how, but I didn't post any assembly
  2605. >>version.  I posted the C version (which therefore has the advantage
  2606. >>that it can be compiled native for PowerPC, or ported easily to another
  2607. >>machine that doesn't even have to be binary, although of course it is
  2608. >>unlikely that shifting will be fast on a non-binary machine).
  2609. >
  2610. >Gosh! What if you read what I wrote above. I didn't claim your code was
  2611. >written in assembly. I refer rather clearly to highly optimized assembly
  2612. >code _equivalent_ to the C code you posted.
  2613.  
  2614. I did read what you wrote.  You have to admit that it isn't all that
  2615. clear.  One could, and I did, read it that you thought I had posted an
  2616. "equivalent hand-coded optimized assembly".
  2617.  
  2618. But as long as we're on the subject of carefully reading each other's
  2619. notes, lets look again at what I said.  I said that Newton/Raphson was
  2620. not the fastest ALGORITHM for taking square roots, because it uses
  2621. several division steps, and there is another algorithm (which I described)
  2622. which is as fast as a single division.  I also made it clear that in
  2623. making that comparison, I was comparing only similar implementations
  2624. of the two operations: my sqare root method implemented entirely in
  2625. software is as fast and about the same size as division implemented
  2626. entirely in software; my square root method implemented entirely in
  2627. hardware is as fast and uses about the same number of logic gates as
  2628. division implemented entirely in hardware.
  2629.  
  2630. Comparing my wholly-software IMPLEMENTATION to your implementation using
  2631. hardware divide is unfair and irrelevant.  I stand by my claim.  Square
  2632. root is no harder or slower than division.  And there is an algorithm
  2633. for square root that will beat Newton/Raphson hands down whenever both
  2634. algorithms are given similar implementations.
  2635.  
  2636. To back up my claim, consider that ANY software-only implementation of 
  2637. Newton/Raphson would have to, as a minimum, test for a zero input (to 
  2638. avoid dividing by zero), and do at least one division.  That is, it would 
  2639. have to be at least as complex as the following routine to compute a 
  2640. sort-of reciprocal:
  2641.  
  2642.     unsigned long lrecip (unsigned long n) {
  2643.         return (n == 0) ? 0 : 0xFFFFFFFF / n;
  2644.         }
  2645.  
  2646. On a 68000, the division has to be done in software, because the 68000
  2647. does not have a DIVU.L instruction.  Examining the code generated by
  2648. this routine shows that its worst-case running time on a 68000 is 1312 
  2649. clocks.  My square-root routine takes at most 1362 clocks.  Close enough?
  2650.  
  2651.  
  2652. >Finally, the point I wanted to make was that an optimized version of
  2653. >Newton's method very well beats an optimized version of the type of
  2654. >algorithm your program is a version of. I'm not interested in any
  2655. >"...b-b-b-but C is more portable..." arguments.
  2656.  
  2657. But I DO care that C is more portable, and it is definitely relevant to
  2658. the comparison.  Our versions were not optimized equivalently, because
  2659. you are focusing only on optimization to a particular piece of silicon
  2660. that happens to implement division, but not square root, in hardware.
  2661. Take our implementations unchanged, and run them on a PowerPC, and mine
  2662. will leave yours in the dust.  ("Unchanged" means I get to compile mine
  2663. native - that's what I bought when I paid the price of being portable.
  2664. "Unchanged" means you have to have yours emulated - that's what you
  2665. bought when you decided to write processor-dependent code.)  Or take
  2666. our implementations unchanged and run them on an Intel processor.  Watch
  2667. mine still run at acceptable speed.  Watch yours not run at all.
  2668.  
  2669. I also care that mine meets the design specs.  The original requestor
  2670. said he wanted to compute square root "rounded to the nearest integer".
  2671. My method rounds, and rounds correctly in every case.  Yours, and all
  2672. the other methods I've seen, truncate.  I can truncate too, if that's
  2673. what you want, but fixing yours to round takes a little work.  Essentially,
  2674. rounding involves comparing the unrounded root with the remainder from
  2675. the last division.  If you implement Newton/Raphson in C or Pascal, that
  2676. remainder is not available to you, and you have to do at least another
  2677. multiply and subtract to get it.  If done in 68K Assembler, the remainder
  2678. is available, so rounding won't slow you down much, but it will complicate
  2679. your logic some, and of course there's that portability issue you don't
  2680. want to talk about.  Either way, remember that rounding may produce a 
  2681. result of 65536, so the routine has to return an unsigned long, just 
  2682. like the requestor asked for, instead of an unsigned short.
  2683.  
  2684. >I've appended below a copy of my code and if you
  2685. >care to compare it to your code, I'll take the time to respond to
  2686. >any comments you might have (size, speed, what have you). Fair?
  2687.  
  2688. Well OK, as long as you keep in mind we're comparing apples to
  2689. oranges.
  2690.  
  2691. Before looking at speed, there is the more important issue of 
  2692. correctness.  As nearly as I can tell, you always return the correct 
  2693. value (except for not rounding).  I won't quite go so far as to say the 
  2694. code is all correct, because you make some early mistakes that get 
  2695. compensated for later:
  2696.  
  2697.   o You test for a zero input by doing a BEQ.S right after moving the
  2698.     input to register A0 for safekeeping.  Are you aware that moving to
  2699.     an A register does not affect the condition codes?  Fortunately,
  2700.     the condition codes are still set correctly from the prior move
  2701.     of the same data from D7 to D0.  However, you have a comment that
  2702.     says that move can be eliminated.  If someone does, they might be 
  2703.     in trouble.
  2704.  
  2705.   o Your logic to do large initial shifts is faulty.  On some inputs (like
  2706.     0x02000000) you overshift.  On other inputs (in the range 512..65535) 
  2707.     I think you are not shifting as far as you think you are shifting.  
  2708.     (The logic around label @skip8 is muddled.)  Fortunately, the Newton 
  2709.     method is robust enough to compensate for a bad initial guess, and
  2710.     you still arrive at the correct answer, although not as efficiently
  2711.     as you could have.
  2712.  
  2713. Maybe you don't care about either of these points - after all, you already 
  2714. said you didn't care about portability - but has no one ever pointed out
  2715. to you that is much easier to write provably correct code in a high level
  2716. language?  Does the fact that your code does not work the way you think it 
  2717. does suggest anything?
  2718.  
  2719. It's hard to estimate your average running time, because there are
  2720. so many paths through the optimization and it's difficult to assign
  2721. proper weights to each path, so I'll settle for comparing worst cases.
  2722.  
  2723.   o Your worst case is with the input 0x02000000, for which you have to
  2724.     do 4 divisions.  You take a total of 994 clocks on a 68000, or
  2725.     459 clocks on a 68020.
  2726.  
  2727.   o My worst case is with the input 0xFFFFFFFF.  I take 1362 clocks on
  2728.     a 68000, 609 on a 68020.
  2729.  
  2730. 1362 / 994 = 1.37.  You are 37% faster than I am on a 68000.
  2731. 609 / 459 = 1.33.  You are 33% faster than I am on a 68020.
  2732.  
  2733. Truth be told, I'm not unhappy that my portable software solution fares
  2734. so well against your non-portable hardware solution, even on the hardware
  2735. of your choice.  Your speed advantage stems from the fact that you are
  2736. coding in Assembler, not from any advantage of the algorithm.  If you 
  2737. implemented your algorithm in C, then either your code would be calling a
  2738. division subroutine (and your performance would go to hell), or you
  2739. could specifically tell the compiler to generate 68020 code to get
  2740. inline divide instructions.  But then, besides no longer running on a 
  2741. 68000, you would still come out behind because the compiler would be
  2742. compelled to generate a DIVU.L instruction instead of your DIVU.W, and 
  2743. that difference alone is enough to dissipate all your advantage.  Add 
  2744. the extra multiply you need to do correct rounding and you're behind.
  2745.  
  2746. -Ron Hunsinger
  2747.  
  2748. +++++++++++++++++++++++++++
  2749.  
  2750. >From christer@cs.umu.se (Christer Ericson)
  2751. Date: Thu, 2 Jun 1994 08:17:18 GMT
  2752. Organization: Dept. of Computing Science, Umea Univ., 901 87 Umea, Sweden
  2753.  
  2754. In <00155867.fc@bmug.org> Ron_Hunsinger@bmug.org (Ron Hunsinger) writes:
  2755. >[...]                                  I also made it clear that in
  2756. >making that comparison, I was comparing only similar implementations
  2757. >of the two operations: my sqare root method implemented entirely in
  2758. >software is as fast and about the same size as division implemented
  2759. >entirely in software; my square root method implemented entirely in
  2760. >hardware is as fast and uses about the same number of logic gates as
  2761. >division implemented entirely in hardware.
  2762.  
  2763. OK, I can agree with that. But apart from that... well, see below.
  2764.  
  2765.  
  2766. >Comparing my wholly-software IMPLEMENTATION to your implementation using
  2767. >hardware divide is unfair and irrelevant.  I stand by my claim.  Square
  2768. >root is no harder or slower than division.  And there is an algorithm
  2769. >for square root that will beat Newton/Raphson hands down whenever both
  2770. >algorithms are given similar implementations.
  2771.  
  2772. It's neither unfair nor irrelevant. You're living in a dream world.
  2773. In the real world (where the rest of us live) there's no such thing
  2774. as "similar implementations". The better (which equals to faster in
  2775. this case) implementation wins, regardless of whether it uses all
  2776. available machine instructions or not.
  2777.  
  2778. In the real world do you always cry, "Not fair! Not fair! You used
  2779. hardware division and I didn't <stomp of feet>."? Hey, good luck to you!
  2780.  
  2781.  
  2782. >But I DO care that C is more portable, and it is definitely relevant to
  2783. >the comparison.  Our versions were not optimized equivalently, because
  2784. >you are focusing only on optimization to a particular piece of silicon
  2785. >that happens to implement division, but not square root, in hardware.
  2786. >Take our implementations unchanged, and run them on a PowerPC, and mine
  2787. >will leave yours in the dust.  ("Unchanged" means I get to compile mine
  2788. >native - that's what I bought when I paid the price of being portable.
  2789. >"Unchanged" means you have to have yours emulated - that's what you
  2790. >bought when you decided to write processor-dependent code.)  Or take
  2791. >our implementations unchanged and run them on an Intel processor.  Watch
  2792. >mine still run at acceptable speed.  Watch yours not run at all.
  2793.  
  2794. You're being silly! I use my code as posted on a 68K machine, I use another
  2795. (general) piece of code on another machine. Ever heard the word #ifdef?
  2796.  
  2797.  
  2798. >I also care that mine meets the design specs.  The original requestor
  2799. >said he wanted to compute square root "rounded to the nearest integer".
  2800. >My method rounds, and rounds correctly in every case.  Yours, and all
  2801. >the other methods I've seen, truncate.  I can truncate too, if that's
  2802. >what you want, but fixing yours to round takes a little work.  Essentially,
  2803. >rounding involves comparing the unrounded root with the remainder from
  2804. >the last division.  If you implement Newton/Raphson in C or Pascal, that
  2805. >remainder is not available to you, and you have to do at least another
  2806. >multiply and subtract to get it.  If done in 68K Assembler, the remainder
  2807. >is available, so rounding won't slow you down much, but it will complicate
  2808. >your logic some, and of course there's that portability issue you don't
  2809. >want to talk about.  Either way, remember that rounding may produce a 
  2810. >result of 65536, so the routine has to return an unsigned long, just 
  2811. >like the requestor asked for, instead of an unsigned short.
  2812.  
  2813. I didn't post my article as a reply to the original post, but as a proof
  2814. that a carefully coded N/B-approach very well outperforms (in terms of
  2815. execution time) the algebraic algorithm your code is a version of.
  2816.  
  2817.  
  2818. >>[I wrote:]
  2819. >>I've appended below a copy of my code and if you
  2820. >>care to compare it to your code, I'll take the time to respond to
  2821. >>any comments you might have (size, speed, what have you). Fair?
  2822. >
  2823. >Well OK, as long as you keep in mind we're comparing apples to
  2824. >oranges.
  2825.  
  2826. I think it's interesting to note that when you compared your code to
  2827. Jim Cathey's code (which you erroneously thought was mine), then you
  2828. thought size was important. Was that only because your code was smaller
  2829. than Cathey's? Now that my code is smaller than yours, it seems that
  2830. you don't think size is important no longer. Nor did you bother to
  2831. compare average times.
  2832.  
  2833. And this from someone who cries "fair" all the time...
  2834.  
  2835.  
  2836. >Before looking at speed, there is the more important issue of 
  2837. >correctness.  As nearly as I can tell, you always return the correct 
  2838. >value (except for not rounding).  I won't quite go so far as to say the 
  2839. >code is all correct, because you make some early mistakes that get 
  2840. >compensated for later:
  2841. >
  2842. >  o You test for a zero input by doing a BEQ.S right after moving the
  2843. >    input to register A0 for safekeeping.  Are you aware that moving to
  2844. >    an A register does not affect the condition codes?  Fortunately,
  2845. >    the condition codes are still set correctly from the prior move
  2846. >    of the same data from D7 to D0.  However, you have a comment that
  2847. >    says that move can be eliminated.  If someone does, they might be 
  2848. >    in trouble.
  2849.  
  2850. Yes this is true. That comment is really a mistake. I added it in haste
  2851. when posting the code to comp.sys.m68k some while ago, when there were
  2852. a discussion of fast implementations of integer square roots. The comment
  2853. is faulty. The code is, and was, correct, however.
  2854.  
  2855.  
  2856. >  o Your logic to do large initial shifts is faulty.  On some inputs (like
  2857. >    0x02000000) you overshift.  On other inputs (in the range 512..65535) 
  2858. >    I think you are not shifting as far as you think you are shifting.  
  2859. >    (The logic around label @skip8 is muddled.)  Fortunately, the Newton 
  2860. >    method is robust enough to compensate for a bad initial guess, and
  2861. >    you still arrive at the correct answer, although not as efficiently
  2862. >    as you could have.
  2863.  
  2864. Harsh words from someone who doesn't bother to attribute code to the
  2865. correct person. There is nothing wrong with the section of code you're
  2866. refering to. That code is there to reduce the number of iterations in
  2867. the section just below, and to _reduce_it_as_much_as_possible_on_average_
  2868. _without_over-complicating_the_code_.
  2869.  
  2870. Now, say again, is it correct or is it faulty? If you consider it to
  2871. be faulty, I'd very much like to see you post what you consider to be
  2872. a correct version!
  2873.  
  2874.  
  2875. >Does the fact that your code does not work the way you think it 
  2876. >does suggest anything?
  2877.  
  2878. While we're being sarcastic, I'd like to ask you if the fact that you
  2879. find errors that aren't there suggest anything to you?
  2880.  
  2881.  
  2882. >It's hard to estimate your average running time, because there are
  2883. >so many paths through the optimization and it's difficult to assign
  2884. >proper weights to each path, so I'll settle for comparing worst cases.
  2885. >
  2886. >  o Your worst case is with the input 0x02000000, for which you have to
  2887. >    do 4 divisions.  You take a total of 994 clocks on a 68000, or
  2888. >    459 clocks on a 68020.
  2889. >
  2890. >  o My worst case is with the input 0xFFFFFFFF.  I take 1362 clocks on
  2891. >    a 68000, 609 on a 68020.
  2892. >
  2893. >1362 / 994 = 1.37.  You are 37% faster than I am on a 68000.
  2894. >609 / 459 = 1.33.  You are 33% faster than I am on a 68020.
  2895.  
  2896. Well, since you didn't bother running the code, I did. On an IIcx I got
  2897. the following results (all numbers in ticks):
  2898.  
  2899. R = Ron's code, as posted
  2900. A = Optimized assembly code equivalent to Ron's code
  2901. C = My code, as posted
  2902.  
  2903.     [0..65536)    [0..500000)    500000 "random" numbers
  2904. R    142        1088        1135
  2905. A    118        906        944
  2906. C    95        626        473
  2907.  
  2908. 142 / 95 = 1.49
  2909. 1088 / 626 = 1.74
  2910. 1135 / 473 = 2.4
  2911.  
  2912. These figures should be considerably larger on a 68000, if we can believe
  2913. your figures. (Note that you could squeeze an extra 20% out of your code,
  2914. which for what is essentially a library routine is quite large. I would use
  2915. my code though.)
  2916.  
  2917.  
  2918. >Truth be told, I'm not unhappy that my portable software solution fares
  2919. >so well against your non-portable hardware solution, even on the hardware
  2920. >of your choice.
  2921.  
  2922. You were saying?
  2923.  
  2924.  
  2925. Christer Ericson --- Internet: christer@cs.umu.se --- tel: +46-90-166794
  2926. Department of Computer Science, University of Umea, S-90187 UMEA, SWEDEN
  2927.  
  2928. ---------------------------
  2929.  
  2930. >From baer@qiclab.scn.rain.com (Ken Baer)
  2931. Subject: How to save alpha in PICT files?
  2932. Date: Sat, 28 May 1994 00:24:17 GMT
  2933. Organization: SCN Research/Qic Laboratories of Tigard, Oregon.
  2934.  
  2935. I need to save 32-bit images as PICT files that include the upper 8 bits
  2936. of data (the alpha buffer).  My code currently saves as 32-bit PICT files,
  2937. but the upper 8-bit of data are missing!  I am using the methods described
  2938. in Inside Mac and developer notes.  The sequence I use now is as follows:
  2939.  - allocate and write 32-bit data to an offscreen GWorld
  2940.  - OpenPicture()
  2941.  - CopyBits(offgworld, offgworld) (copy the pixmap to itself)
  2942.  - ClosePicture()
  2943.  
  2944. Is there an extra writing step to jam in the alpha buffer?  Is there any
  2945. sample code (in C) with a more modern method?  The sample code I'm working
  2946. from is pretty dated.
  2947.  
  2948. Thanks in advance.
  2949.  
  2950.     -Ken Baer.
  2951.     baer@qiclab.scn.rain.com
  2952. -- 
  2953.  \_       -Ken Baer.  Programmer/Animator, Hash Inc.
  2954. <[_]   Usenet: baer@qiclab.scn.rain.com/AppleLink:KENBAER/Office: (206)750-0042
  2955.  =# \, Animation Master: Finally, 3D animation software an artist can afford!
  2956.  
  2957. +++++++++++++++++++++++++++
  2958.  
  2959. >From zapper2@netcom.com (Chris Athanas)
  2960. Date: Sun, 29 May 1994 09:19:37 GMT
  2961. Organization: NETCOM On-line Communication Services (408 261-4700 guest)
  2962.  
  2963. Ken Baer (baer@qiclab.scn.rain.com) wrote:
  2964. : I need to save 32-bit images as PICT files that include the upper 8 bits
  2965. : of data (the alpha buffer).  My code currently saves as 32-bit PICT files,
  2966. : but the upper 8-bit of data are missing!  I am using the methods described
  2967. : in Inside Mac and developer notes.  The sequence I use now is as follows:
  2968. :  - allocate and write 32-bit data to an offscreen GWorld
  2969. :  - OpenPicture()
  2970. :  - CopyBits(offgworld, offgworld) (copy the pixmap to itself)
  2971. :  - ClosePicture()
  2972.  
  2973. : Is there an extra writing step to jam in the alpha buffer?  Is there any
  2974. : sample code (in C) with a more modern method?  The sample code I'm working
  2975. : from is pretty dated.
  2976.  
  2977. Under system 6.0, you could use the upper 8 bits as an alpha channel.
  2978. >From what I understand, that was a bug.
  2979.  
  2980. Current PICT files only support 24-bit images. The upper 8bits are 
  2981. truncated, and the picture is stored as 24-bits per pixel.
  2982.  
  2983. To associate an alpha channel with a PICT, you will need to do some 
  2984. custom stuff. I'm not sure what your application is, but if you are doing 
  2985. everything yuorself, you could store the normal picture as a 24-bit pict 
  2986. file (normal PICT file) and create a PICT resource in that file that 
  2987. contains the alpha channel. This way "normal" applications can use your 
  2988. data-fork PICT file normally, and you can use your alpha channel in your 
  2989. own apps.
  2990.  
  2991. Also, if you are planning on using photoshop, photoshop has a buil-in 
  2992. filter that allows you to take a PICT resource from a file. So your users 
  2993. could still have access to your "custom" alpha channel in photoshop.
  2994.  
  2995. Another alternative is to use the photoshop standard as your file format. 
  2996. The ps format allows for as many channels as you would like. And 
  2997. photoshop is a pretty standard application now, and is widely used.
  2998.  
  2999. Hope this helps.
  3000.  
  3001. Chris Athanas
  3002.  
  3003. +++++++++++++++++++++++++++
  3004.  
  3005. >From baer@qiclab.scn.rain.com (Ken Baer)
  3006. Date: Mon, 30 May 1994 17:51:58 GMT
  3007. Organization: SCN Research/Qic Laboratories of Tigard, Oregon.
  3008.  
  3009. In article <zapper2CqK4Kq.Fn2@netcom.com> zapper2@netcom.com (Chris Athanas) writes:
  3010. >Ken Baer (baer@qiclab.scn.rain.com) wrote:
  3011. >: I need to save 32-bit images as PICT files that include the upper 8 bits
  3012. >: of data (the alpha buffer).  My code currently saves as 32-bit PICT files,
  3013. >: but the upper 8-bit of data are missing!  I am using the methods described
  3014. >: in Inside Mac and developer notes.  The sequence I use now is as follows:
  3015. >:  - allocate and write 32-bit data to an offscreen GWorld
  3016. >:  - OpenPicture()
  3017. >:  - CopyBits(offgworld, offgworld) (copy the pixmap to itself)
  3018. >:  - ClosePicture()
  3019. >
  3020. >: Is there an extra writing step to jam in the alpha buffer?  Is there any
  3021. >: sample code (in C) with a more modern method?  The sample code I'm working
  3022. >: from is pretty dated.
  3023. >
  3024. >Under system 6.0, you could use the upper 8 bits as an alpha channel.
  3025. >From what I understand, that was a bug.
  3026.  
  3027. A damn useful bug.  I guess 32-bit QuickDraw was a typo too :-(.
  3028.  
  3029. >Current PICT files only support 24-bit images. The upper 8bits are 
  3030. >truncated, and the picture is stored as 24-bits per pixel.
  3031.  
  3032. What's the logic behind this?  Or as Seinfeld would say, "Who are the 
  3033. programming wizards that came up with this one?!?"
  3034.  
  3035. >To associate an alpha channel with a PICT, you will need to do some 
  3036. >custom stuff. I'm not sure what your application is, but if you are doing 
  3037. >everything yuorself, you could store the normal picture as a 24-bit pict 
  3038. >file (normal PICT file) and create a PICT resource in that file that 
  3039. >contains the alpha channel. This way "normal" applications can use your 
  3040. >data-fork PICT file normally, and you can use your alpha channel in your 
  3041. >own apps.
  3042.  
  3043. The application in question is a 3D renderer which normally outputs 
  3044. QuickTime (which has no problem dealing with real 32-bit data), but will
  3045. also put out Targa, PICS, and PICT.  I want PICT files with an alpha
  3046. channel that can be used primarily in Photoshop, and in other applications
  3047. that support 32-bit PICT files.
  3048.  
  3049. >Also, if you are planning on using photoshop, photoshop has a buil-in 
  3050. >filter that allows you to take a PICT resource from a file. So your users 
  3051. >could still have access to your "custom" alpha channel in photoshop.
  3052.  
  3053. Are you saying that Photoshop uses the alpha in a resource method that you
  3054. described above?  Is this documented anywhere?
  3055.  
  3056. >
  3057. >Another alternative is to use the photoshop standard as your file format. 
  3058. >The ps format allows for as many channels as you would like. And 
  3059. >photoshop is a pretty standard application now, and is widely used.
  3060.  
  3061. I'd rather stick with PICT, though it is easily my leasy favorite image
  3062. format.  It's really a shame that the Mac standard format is also the
  3063. least portable to other systems.  It's a big deal to us since our
  3064. application also runs on Windows and SGI.
  3065.  
  3066. >
  3067. >Hope this helps.
  3068.  
  3069. Yes, it does.  My big question is what is everyone else doing for saving
  3070. alpha with PICT files?
  3071.  
  3072. >
  3073. >Chris Athanas
  3074.  
  3075.  
  3076. -- 
  3077.  \_       -Ken Baer.  Programmer/Animator, Hash Inc.
  3078. <[_]   Usenet: baer@qiclab.scn.rain.com/AppleLink:KENBAER/Office: (206)750-0042
  3079.  =# \, Animation Master: Finally, 3D animation software an artist can afford!
  3080.  
  3081. +++++++++++++++++++++++++++
  3082.  
  3083. >From scottsquir@aol.com (ScottSquir)
  3084. Date: 30 May 1994 18:54:02 -0400
  3085. Organization: America Online, Inc. (1-800-827-6364)
  3086.  
  3087. In article <1994May30.175158.28837@qiclab.scn.rain.com>,
  3088. baer@qiclab.scn.rain.com (Ken Baer) writes:
  3089.  
  3090. > My big question is what is everyone else doing for saving
  3091. >alpha with PICT files?
  3092.  
  3093. Set the cmpCount in the GWorld pixmap to 4.  It defaults to 3.
  3094.  
  3095. If you resize or do other CopyBits manipulation it may get lost.
  3096. -scott
  3097.  
  3098.  
  3099. +++++++++++++++++++++++++++
  3100.  
  3101. >From Darrin.Cardani@AtlantaGA.NCR.COM (Darrin Cardani)
  3102. Date: Tue, 31 May 1994 18:17:38 GMT
  3103. Organization: UNITY, AT&T GIS
  3104.  
  3105. In article <1994May30.175158.28837@qiclab.scn.rain.com> baer@qiclab.scn.rain.com (Ken Baer) writes:
  3106.  
  3107. >Are you saying that Photoshop uses the alpha in a resource method that you
  3108. >described above?  Is this documented anywhere?
  3109.  
  3110. You can get all the docs on Photoshop's format from archive.umich.edu in the
  3111. mac/graphics/util directory. (Might be mac/development directory, actually, I'm
  3112. not sure).
  3113.  
  3114. >>
  3115. >>Another alternative is to use the photoshop standard as your file format. 
  3116. >>The ps format allows for as many channels as you would like. And 
  3117. >>photoshop is a pretty standard application now, and is widely used.
  3118.  
  3119. >Yes, it does.  My big question is what is everyone else doing for saving
  3120. >alpha with PICT files?
  3121.  
  3122. I'm currently saving them as 2 PICT files. I've debated using 1 file with 2
  3123. PICT resources in it. I think I'll end up using the Photoshop method, because
  3124. it adds usefulness to my program.
  3125.  
  3126. Also, someone mentioned you could have as many channels as needed with the
  3127. photoshop format, I believe you can only have up to 16, though.
  3128.  
  3129. >-- 
  3130. > \_       -Ken Baer.  Programmer/Animator, Hash Inc.
  3131. ><[_]   Usenet: baer@qiclab.scn.rain.com/AppleLink:KENBAER/Office: (206)750-0042
  3132. > =# \, Animation Master: Finally, 3D animation software an artist can afford!
  3133.  
  3134. Really? What it is and can a demo be downloaded anywhere?
  3135.  
  3136. Darrin
  3137.  
  3138. Darrin Cardani
  3139. Opinions above are mine. Mine! Mine! Mine!
  3140. Darrin.Cardani@AtlantaGA.NCR.COM
  3141.  
  3142. +++++++++++++++++++++++++++
  3143.  
  3144. >From a ()
  3145. Date: 2 Jun 1994 01:11:24 GMT
  3146. Organization: Apple Computer, Inc., Cupertino, California
  3147.  
  3148. In article <1994May30.175158.28837@qiclab.scn.rain.com>,
  3149. baer@qiclab.scn.rain.com (Ken Baer) wrote:
  3150.  
  3151. > In article <zapper2CqK4Kq.Fn2@netcom.com> zapper2@netcom.com (Chris Athanas) writes:
  3152. > >Ken Baer (baer@qiclab.scn.rain.com) wrote:
  3153. > >: I need to save 32-bit images as PICT files that include the upper 8 bits
  3154. > >: of data (the alpha buffer).  My code currently saves as 32-bit PICT files,
  3155. > >: but the upper 8-bit of data are missing!  I am using the methods described
  3156. > >: in Inside Mac and developer notes.  The sequence I use now is as follows:
  3157. > >:  - allocate and write 32-bit data to an offscreen GWorld
  3158. > >:  - OpenPicture()
  3159. > >:  - CopyBits(offgworld, offgworld) (copy the pixmap to itself)
  3160. > >:  - ClosePicture()
  3161. > >
  3162. > >: Is there an extra writing step to jam in the alpha buffer?  Is there any
  3163. > >: sample code (in C) with a more modern method?  The sample code I'm working
  3164. > >: from is pretty dated.
  3165. > >
  3166. > >Under system 6.0, you could use the upper 8 bits as an alpha channel.
  3167. > >From what I understand, that was a bug.
  3168. > A damn useful bug.  I guess 32-bit QuickDraw was a typo too :-(.
  3169. > >Current PICT files only support 24-bit images. The upper 8bits are 
  3170. > >truncated, and the picture is stored as 24-bits per pixel.
  3171. > What's the logic behind this?  Or as Seinfeld would say, "Who are the 
  3172. > programming wizards that came up with this one?!?"
  3173. > >To associate an alpha channel with a PICT, you will need to do some 
  3174. > >custom stuff. I'm not sure what your application is, but if you are doing 
  3175. > >everything yuorself, you could store the normal picture as a 24-bit pict 
  3176. > >file (normal PICT file) and create a PICT resource in that file that 
  3177. > >contains the alpha channel. This way "normal" applications can use your 
  3178. > >data-fork PICT file normally, and you can use your alpha channel in your 
  3179. > >own apps.
  3180. > The application in question is a 3D renderer which normally outputs 
  3181. > QuickTime (which has no problem dealing with real 32-bit data), but will
  3182. > also put out Targa, PICS, and PICT.  I want PICT files with an alpha
  3183. > channel that can be used primarily in Photoshop, and in other applications
  3184. > that support 32-bit PICT files.
  3185. > >Also, if you are planning on using photoshop, photoshop has a buil-in 
  3186. > >filter that allows you to take a PICT resource from a file. So your users 
  3187. > >could still have access to your "custom" alpha channel in photoshop.
  3188. > Are you saying that Photoshop uses the alpha in a resource method that you
  3189. > described above?  Is this documented anywhere?
  3190. > >
  3191. > >Another alternative is to use the photoshop standard as your file format. 
  3192. > >The ps format allows for as many channels as you would like. And 
  3193. > >photoshop is a pretty standard application now, and is widely used.
  3194. > I'd rather stick with PICT, though it is easily my leasy favorite image
  3195. > format.  It's really a shame that the Mac standard format is also the
  3196. > least portable to other systems.  It's a big deal to us since our
  3197. > application also runs on Windows and SGI.
  3198. > >
  3199. > >Hope this helps.
  3200. > Yes, it does.  My big question is what is everyone else doing for saving
  3201. > alpha with PICT files?
  3202. > >
  3203. > >Chris Athanas
  3204. > -- 
  3205. >  \_       -Ken Baer.  Programmer/Animator, Hash Inc.
  3206. > <[_]   Usenet: baer@qiclab.scn.rain.com/AppleLink:KENBAER/Office: (206)750-0042
  3207. >  =# \, Animation Master: Finally, 3D animation software an artist can afford!
  3208.  
  3209. The technique is described in IM VI pp 17-22 through 17-23; basically the
  3210. idea is that before calling CopyBits you need to set the packType field in
  3211. the source pixmap to four and the cmpCount to 4 also.
  3212.  
  3213. Hope this really helps.
  3214.  
  3215. Guillermo
  3216.  
  3217. ---------------------------
  3218.  
  3219. >From wingo@apple.com (Tony Wingo)
  3220. Subject: Open Transport & ASLM
  3221. Date: Thu, 2 Jun 1994 18:06:30 GMT
  3222. Organization: Apple Computer
  3223.  
  3224. The following is a response from the Open Transport Team to the recent
  3225. threads on OpenTransport, ASLM and DLL's in general.
  3226.  
  3227. Comments may be sent to opentpt@applelink.apple.com
  3228.  
  3229. =====================================================================
  3230.  
  3231. When Open Transport was developed, ASLM was the only general option
  3232. for dynamic linking - CFM and SOM were not anywhere in sight. In
  3233. fact, today we still can only use CFM for dynamic linking on PowerPC.
  3234. It's not available for 68K, and SOM is not available for either
  3235. platform.
  3236.  
  3237. Whether or not ASLM is used as the dynamic linking mechanism, the
  3238. fact that C++ objects generated by different compilers have different
  3239. formats makes it virtually impossible to export object-oriented
  3240. interfaces that everyone can use.  Yes - SOM will solve this problem,
  3241. but that solution does not come without a performance penalty -
  3242. parameters have to be marshalled, and solving the fragile base class
  3243. problem requires a much more indirect method of dispatching than a
  3244. jump through a vtable.  
  3245.  
  3246. We really wanted to be able to create an object-oriented framework
  3247. for writing STREAMS modules, and ASLM allowed us to do that without a
  3248. performance penalty.   Now that CFM and SOM are either here or on the
  3249. horizon, we've backed off of that goal.
  3250.  
  3251. >From a client perspective, Open Transport supports a complete
  3252. procedural interface using Pascal calling conventions for use in the
  3253. widest range of development environments possible.  It also has a C++
  3254. object interface, which is usable with MPW Cfront, and with the PPCC
  3255. Script/tools for PowerPC.  We believe that the C++ interface is also
  3256. usable from Symantec C++ for 68K, but this has not been tested. We
  3257. have also not tested with the Metrowerks products, but are assuming
  3258. that, like Symantec, they have a way to import MPW .o and XCOFF
  3259. files.
  3260.  
  3261. ASLM is currently used as the dynamically loading mechanism for both
  3262. client code and STREAMS modules, but neither version REQUIRES using
  3263. C++ interface.  
  3264.  
  3265. When SOM becomes available as part of the system, we will look at
  3266. converting our C++ client interfaces to become SOM objects.  The
  3267. procedural interfaces for STREAMS modules will remain ASLM-based for
  3268. 68K and CFM-based for PowerPC.
  3269.  
  3270. The bottom line is:  If you can't get Open Transport client files to
  3271. link with your tools using our "C" interfaces, then either your tools
  3272. don't support MPW-generated libraries,  your tools can't deal with
  3273. Pascal calling conventions, or the Open Transport team has a bug.
  3274.  
  3275. We have not yet published any information on how to write a STREAM
  3276. module for Open Transport.  As soon as we do, it will tell you how to
  3277. create both ASLM and CFM-based STREAM modules.
  3278.  
  3279. I hope this clears up any misunderstandings on using Open Transport.
  3280.  
  3281. ---------------------------
  3282.  
  3283. >From kennedy@fenton.cs.udcavis.edu (Kennedy)
  3284. Subject: Sending the Mac Screen Image
  3285. Date: Thu, 2 Jun 1994 01:56:33 GMT
  3286. Organization: University of California, Davis
  3287.  
  3288.  
  3289.     This might be too involved of a question for this news group
  3290. But I was wondering if anyone had any Ideas. What I need to do is 
  3291. send screen image of a Macintosh so that it can be viewed in all
  3292. its glory in an X window. The screen should refresh flicker free
  3293. and should look to the viewer of the X window as is he/she was 
  3294. looking at the Mac monitor. This has to be done using TCP/IP. 
  3295.      If you have any Ideas, example code, algorithms, or whether 
  3296. you think it can be done or not, let me know. Thanx.
  3297.  
  3298. Brian Kennedy (kennedy@fenton.cs.ucdavis.edu)
  3299.  
  3300.  
  3301. +++++++++++++++++++++++++++
  3302.  
  3303. >From rmah@panix.com (Robert S. Mah)
  3304. Date: Thu, 02 Jun 1994 01:22:22 -0500
  3305. Organization: One Step Beyond
  3306.  
  3307. kennedy@fenton.cs.udcavis.edu (Kennedy) wrote:
  3308.  
  3309. >     This might be too involved of a question for this news group
  3310. > But I was wondering if anyone had any Ideas. What I need to do is 
  3311. > send screen image of a Macintosh so that it can be viewed in all
  3312. > its glory in an X window. The screen should refresh flicker free
  3313. > and should look to the viewer of the X window as is he/she was 
  3314. > looking at the Mac monitor. This has to be done using TCP/IP. 
  3315. >      If you have any Ideas, example code, algorithms, or whether 
  3316. > you think it can be done or not, let me know. Thanx.
  3317.  
  3318. Since you said "in all its glory" I take it you mean color.
  3319.  
  3320. Let's see...640x480 minimum screen size means 300K per frame.  At 24 fps,
  3321. that's around 7MBytes per second.  Too much.
  3322.  
  3323. You'll have to send screen differences (i.e. just what changed on the 
  3324. screen) to get a decent frame rate.  Keep a copy of the screen image on
  3325. the Mac, note the changes, send it via TCP/IP.  Receive it on the UNIX 
  3326. machine.  Have the X Server send it to the X Client.
  3327.  
  3328. You could also patch all of QuickDraw and send the QD command opcodes to
  3329. the UNIX box.  There, you'd have to write a QD emulator and execute the
  3330. opcodes as they come in.  This would be very hard to write, but would 
  3331. work faster than the screen difference method.
  3332.  
  3333. Have you considered just buying it.  I think there are a few products 
  3334. that do this out there.
  3335.  
  3336. Cheers,
  3337. Rob
  3338. ___________________________________________________________________________
  3339. Robert S. Mah  -=-  One Step Beyond  -=-  212-947-6507  -=-  rmah@panix.com
  3340.  
  3341. +++++++++++++++++++++++++++
  3342.  
  3343. >From David K}gedal <davidk@lysator.liu.se>
  3344. Date: 2 Jun 1994 11:44:58 GMT
  3345. Organization: Lysator Academic Computer Society
  3346.  
  3347. In article <rmah-020694012222@rmah.dialup.access.net> Robert S. Mah,
  3348. rmah@panix.com writes:
  3349. >You'll have to send screen differences (i.e. just what changed on the 
  3350. >screen) to get a decent frame rate.  Keep a copy of the screen image on
  3351. >the Mac, note the changes, send it via TCP/IP.  Receive it on the UNIX 
  3352. >machine.  Have the X Server send it to the X Client.
  3353.  
  3354. Oops, this is a very common confusion. It is of course the X client that 
  3355. will send it to the X server. The server is the one that controls the 
  3356. actual screen and does the drawing that the clients tells it to do.
  3357.  
  3358.  /David
  3359.  
  3360. +++++++++++++++++++++++++++
  3361.  
  3362. >From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
  3363. Date: 2 Jun 1994 12:56:48 GMT
  3364. Organization: The Royal Institute of Technology
  3365.  
  3366. In <rmah-020694012222@rmah.dialup.access.net> rmah@panix.com (Robert S. Mah) writes:
  3367.  
  3368. >Let's see...640x480 minimum screen size means 300K per frame.  At 24 fps,
  3369. >that's around 7MBytes per second.  Too much.
  3370.  
  3371. You only need send what's drawn, and you can compress it while you
  3372. send.
  3373.  
  3374. There are commercial apps that do EXACTLY this. There are two
  3375. mechanisms you can use; patching the QuickDraw bottlenecks, or
  3376. patching ShieldCursor().
  3377.  
  3378. QuickDraw does all drawing through bottlenecks, so if you want
  3379. object graphics, send the bottleneck commands across the network.
  3380. You have to send port information as well, I guess.
  3381.  
  3382. QuickDraw also calls ShieldCursor() for the enclosing rectangle of
  3383. what it draws, and ShowCursor() when it's done, so if you only
  3384. want a bitmap, use that area, and send the (packed) bitmap once
  3385. drawing is done (ShowCursor() time) or accumulate it all into a
  3386. region which you send at WaitNextEvent time.
  3387. -- 
  3388.  -- Jon W{tte, h+@nada.kth.se, Mac Software Engineer Deluxe --
  3389.    This signature is kept shorter than 4 lines in the interests of UseNet
  3390.    S/N ratio.
  3391.  
  3392. +++++++++++++++++++++++++++
  3393.  
  3394. >From rmah@panix.com (Robert S. Mah)
  3395. Date: Thu, 02 Jun 1994 11:40:51 -0500
  3396. Organization: One Step Beyond
  3397.  
  3398. David K}gedal <davidk@lysator.liu.se> wrote:
  3399.  
  3400. > Robert S. Mah, rmah@panix.com writes:
  3401. > >You'll have to send screen differences (i.e. just what changed on the 
  3402. > >screen) to get a decent frame rate.  Keep a copy of the screen image on
  3403. > >the Mac, note the changes, send it via TCP/IP.  Receive it on the UNIX 
  3404. > >machine.  Have the X Server send it to the X Client.
  3405. > Oops, this is a very common confusion. It is of course the X client that 
  3406. > will send it to the X server. The server is the one that controls the 
  3407. > actual screen and does the drawing that the clients tells it to do.
  3408.  
  3409. Right.  I don't do X, so I'm more than a bit hazy about this stuff, but
  3410. after you mentioned it, I did recall reading an article about this and
  3411. saying to myself, "That's supposed to make sense?"
  3412.  
  3413. So, to correct myself...the X-client would ask the X-server to draw the
  3414. stuff.  Hey...couldn't you simply put the X-client on the Mac?  Could
  3415. be an interesting academic project.
  3416.  
  3417. Cheers,
  3418. Rob
  3419. ___________________________________________________________________________
  3420. Robert S. Mah  -=-  One Step Beyond  -=-  212-947-6507  -=-  rmah@panix.com
  3421.  
  3422. ---------------------------
  3423.  
  3424. >From jaffe@rabbit.cita.utoronto.ca (Andrew Jaffe)
  3425. Subject: What are Universal Headers?
  3426. Date: Thu, 19 May 1994 13:49:41 GMT
  3427. Organization: CITA
  3428.  
  3429.  
  3430. That's about it:
  3431.     What are the Universal Headers?
  3432.  
  3433. AJ
  3434. --
  3435. - --------------------------------------------------------------------
  3436. Andrew Jaffe                    jaffe@cita.utoronto.ca
  3437. CITA, U. Toronto                (416) 978-8497, 6879
  3438. 60 Saint George St.                         -3921 (Fax)
  3439. Toronto, ON M5S 1A1 CANADA            
  3440.  
  3441. +++++++++++++++++++++++++++
  3442.  
  3443. >From dean@genmagic.com (Dean Yu)
  3444. Date: 19 May 1994 17:20:31 GMT
  3445. Organization: General Magic, Inc.
  3446.  
  3447. In article <JAFFE.94May19094941@rabbit.cita.utoronto.ca>,
  3448. jaffe@rabbit.cita.utoronto.ca (Andrew Jaffe) wrote:
  3449. > That's about it:
  3450. >     What are the Universal Headers?
  3451.  
  3452.   Universal Headers are the twisted idea of a couple of system software
  3453. engineers who have since left the company to try to avoid the proliferation
  3454. of interface files as the Mac API was going cross platform. That is, rather
  3455. than having a set of header files you compile with if you were doing say a
  3456. PowerPC application, and different set you use if you were doing a 68K
  3457. application, you would have one set that can be used for any platform that
  3458. supplied the Mac API by flipping a couple of compile time switches.
  3459.   Like any grand unifying theory, it was very elusive, long in the coming,
  3460. and probably a little less all-encompassing than it should have been.
  3461.  
  3462. -- Dean Yu
  3463.    Negative Ethnic Role Model
  3464.    General Magic, Inc.
  3465.  
  3466. +++++++++++++++++++++++++++
  3467.  
  3468. >From Lars.Farm@nts.mh.se (Lars Farm)
  3469. Date: Fri, 20 May 1994 09:43:17 +0100
  3470. Organization: Mid Sweden University
  3471.  
  3472. In article <dean-190594101355@dean_yu.genmagic.com>, dean@genmagic.com
  3473. (Dean Yu) wrote:
  3474.  
  3475. > In article <JAFFE.94May19094941@rabbit.cita.utoronto.ca>,
  3476. > jaffe@rabbit.cita.utoronto.ca (Andrew Jaffe) wrote:
  3477. > > 
  3478. > > That's about it:
  3479. > >     What are the Universal Headers?
  3480. > > 
  3481. >   Universal Headers are the twisted idea of a couple of system software
  3482. [...]
  3483. >   Like any grand unifying theory, it was very elusive, long in the coming,
  3484. > and probably a little less all-encompassing than it should have been.
  3485.  
  3486. Still, it is very nice to have _one_ set of Mac headers, after all there is
  3487. only one API. Now it's a lot simpler to move code between compilers. This
  3488. can't be bad.
  3489.  
  3490. -- 
  3491. Lars.Farm@nts.mh.se
  3492.  
  3493. +++++++++++++++++++++++++++
  3494.  
  3495. >From slosser@apple.com (Eric Slosser)
  3496. Date: Sat, 28 May 1994 21:14:40 GMT
  3497. Organization: Apple Computer, Inc.
  3498.  
  3499. > In article <dean-190594101355@dean_yu.genmagic.com>, dean@genmagic.com
  3500. > (Dean Yu) wrote:
  3501. > > 
  3502. > >   Universal Headers are the twisted idea of a couple of system software
  3503. > [...]
  3504. > >   Like any grand unifying theory, it was very elusive, long in the coming,
  3505. > > and probably a little less all-encompassing than it should have been.
  3506.  
  3507. Well, with the kind of people they had working on the project, what did you
  3508. expect, Dean?
  3509.  
  3510. PS.  Don't forget the really novel idea of having the C, Pascal, and Asm
  3511. headers auto-generated from a master file, rather than maintained by hand.
  3512.  
  3513. -- 
  3514. Eric Slosser / Apple Computer / slosser@apple.com
  3515.  
  3516. +++++++++++++++++++++++++++
  3517.  
  3518. >From jum@anubis.han.de (Jens-Uwe Mager)
  3519. Date: Thu, 2 Jun 94 01:05:11 MET
  3520. Organization: (none)
  3521.  
  3522.  
  3523. In article <slosser-280594131440@mac96.kip.apple.com> (comp.sys.mac.programmer), slosser@apple.com (Eric Slosser) writes:
  3524.  
  3525. > PS.  Don't forget the really novel idea of having the C, Pascal, and Asm
  3526. > headers auto-generated from a master file, rather than maintained by hand.
  3527.  
  3528.  
  3529. Hmmm, how does your specification language look like?
  3530.  
  3531. ______________________________________________________________________________
  3532. Jens-Uwe Mager            jum@anubis.han.de
  3533. 30177 Hannover            jum@helios.de
  3534. Brahmsstr. 3            Tel.: +49 511 660238
  3535.  
  3536. ---------------------------
  3537.  
  3538. End of C.S.M.P. Digest
  3539. **********************
  3540.  
  3541.  
  3542. ˇ